从tar.gz的grep没有解压缩

我试图从十几个文件.tar.gz grep模式,但它很慢

正在使用

tar -ztf file.tar.gz | while read FILENAME do if tar -zxf file.tar.gz "$FILENAME" -O | grep "string" > /dev/null then echo "$FILENAME contains string" fi done 

Solutions Collecting From Web of "从tar.gz的grep没有解压缩"

如果你有zgrep你可以使用

 zgrep -a string file.tar.gz 

您可以使用--to-command选项将文件传送到任意脚本。 使用此功能,您可以一次性处理存档(并且不需要临时文件)。 另见这个问题和手册 。 有了以上的信息,你可以尝试像这样:

 $ tar xf file.tar.gz --to-command "awk '/bar/ { print ENVIRON[\"TAR_FILENAME\"]; exit }'" bfe2/.bferc bfe2/CHANGELOG bfe2/README.bferc 

如果这真的很慢,我怀疑你正在处理一个大档案文件。 它将解压缩一次以提取文件列表,然后将其解压缩N次,其中N是归档文件中的文件数目,用于​​grep。 除了所有的解压缩之外,每次都需要将相当一部分扫描到归档文件中以提取每个文件。 tar最大的缺点之一就是一开始就没有内容表。 没有有效的方法来获取有关档案中所有文件的信息,只能读取文件的这一部分。 它基本上必须读取所有的文件,直到你每次提取的东西; 它不能马上跳到文件名的位置。

你可以做的最简单的事情就是先解压文件( gunzip file.tar.gz )然后在.tar文件上工作。 这本身可能有足够的帮助。 尽管如此,它仍然会遍历整个存档。

如果你真的希望这是有效的,你唯一的选择是在处理之前完整地提取存档中的所有内容。 由于你的问题是速度,我怀疑这是一个你不想首先提取的巨大文件,但是如果可以的话,这将会加快速度。

 tar zxf file.tar.gz for f in hopefullySomeSubdir/*; do grep -l "string" $f done 

请注意, grep -l打印任何匹配文件的名称,在第一次匹配之后退出,如果不匹配,则为无提示。 仅此一项就会加速你的命令中的grep -l部分,所以即使你没有足够的空间去提取整个压缩文件, grep -l也会有所帮助。 如果文件很大,会有很大的帮助。

我知道这个问题是4岁,但我有几个不同的选择:

选项1:使用tar --to-command grep

下面一行将在example.tgz查找PATTERN 。 这与@ Jester的例子类似,但是我无法让他的模式匹配工作。

 tar xzf example.tgz --to-command 'grep --label="$TAR_FILENAME" -H PATTERN ; true' 

选项2:使用tar -tzf

第二个选项是使用tar -tzf来列出文件,然后用grep来查看它们。 你可以创建一个函数来反复使用它:

 targrep () { for i in $(tar -tzf "$1"); do results=$(tar -Oxzf "$1" "$i" | grep --label="$i" -H "$2") echo "$results" done } 

用法:

 targrep example.tar.gz "pattern" 

对于初学者,你可以启动多个进程:

 tar -ztf file.tar.gz | while read FILENAME do (if tar -zxf file.tar.gz "$FILENAME" -O | grep -l "string" then echo "$FILENAME contains string" fi) & done 

( ... ) &创建一个新的分离(读取:父shell不等待子进程)。

之后,你应该优化你的档案的提取。 读取没有问题,因为操作系统应该已经缓存了文件访问权限。 但是,tar每次循环运行时都需要解压缩文件,这可能会很慢。 解压存档一次并迭代结果可能会有所帮助:

 local tempPath=`tempfile` mkdir $tempPath && tar -zxf file.tar.gz -C $tempPath && find $tempPath -type f | while read FILENAME do (if grep -l "string" "$FILENAME" then echo "$FILENAME contains string" fi) & done && rm -r $tempPath 

在这里使用find来获取tar目标目录中的文件列表,我们正在迭代这个文件,用于搜索字符串的每个文件。

编辑:使用grep -l加快速度,正如Jim所指出的那样。 从man grep

  -l, --files-with-matches Suppress normal output; instead print the name of each input file from which output would normally have been printed. The scanning will stop on the first match. (-l is specified by POSIX.)