来自tar.gz的grep没有提取[更快的]

Pix*_*xel 48 linux bash 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
Run Code Online (Sandbox Code Playgroud)

lan*_*nes 107

如果你有,zgrep你可以使用

zgrep -a string file.tar.gz
Run Code Online (Sandbox Code Playgroud)

  • zgrep不处理tar文件,所以这不是一个正确的答案.@Jester的答案确实做了正确的事情 (6认同)
  • `zgrep`很酷,但请注意,除了OP想要的东西之外,这还有其他功能. (4认同)
  • @Jim我的`zgrep` **确实可以处理tar文件(.tar.gz),此解决方案对我有用(Red Hat 4.4.7-16; zgrep(gzip)1.3.12)。另一方面,Jesters解决方案对我不起作用。从awk到标准输出,它提供了一些坏的管道异常。 (3认同)

Jes*_*ter 31

您可以使用该--to-command选项将文件传输到任意脚本.使用此功能,您可以一次性处理存档(并且没有临时文件).另请参阅此问题手册.有了上述信息,您可以尝试以下方法:

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

  • @Kayvar 注意到我们正在 grep 文件内容,但打印文件名(如 OP 想要的)。 (2认同)

Kat*_*tie 6

我知道这个问题已经4岁了,但是我有两种选择:

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

下面的行应该在example.tgzPATTERN。这类似于@Jester的示例,但是我无法使他的模式匹配起作用。

tar xzf example.tgz --to-command 'grep --label="$TAR_FILENAME" -H PATTERN ; true'
Run Code Online (Sandbox Code Playgroud)

选项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
}
Run Code Online (Sandbox Code Playgroud)

用法:

targrep example.tar.gz "pattern"
Run Code Online (Sandbox Code Playgroud)


Nut*_*tan 6

以下两个选项都运行良好。

$ zgrep -ai 'CDF_FEED' FeedService.log.1.05-31-2019-150003.tar.gz | more
2019-05-30 19:20:14.568 ERROR 281 --- [http-nio-8007-exec-360] DrupalFeedService  : CDF_FEED_SERVICE::CLASSIFICATION_ERROR:408: Classification failed even after maximum retries for url : abcd.html

$ zcat FeedService.log.1.05-31-2019-150003.tar.gz | grep -ai 'CDF_FEED'
2019-05-30 19:20:14.568 ERROR 281 --- [http-nio-8007-exec-360] DrupalFeedService  : CDF_FEED_SERVICE::CLASSIFICATION_ERROR:408: Classification failed even after maximum retries for url : abcd.html
Run Code Online (Sandbox Code Playgroud)

  • `zgrep` 和她的配偶,如 `zcat` 确实很好,但不处理 tar 文件。OP 需要 tarball 中匹配的文件名。 (2认同)

nem*_*emo 4

对于初学者来说,您可以启动多个进程:

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
Run Code Online (Sandbox Code Playgroud)

创建( ... ) &一个新的分离(读:父 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
Run Code Online (Sandbox Code Playgroud)

find此处使用,获取 的目标目录中的文件列表tar(我们正在迭代该目录),其中每个文件都搜索字符串。

编辑:grep -l正如吉姆指出的那样,用于加快速度。从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.)
Run Code Online (Sandbox Code Playgroud)

  • 这里还有一些很好的解决方案,但我强烈建议使用 `grep -l` 代替 `grep` 和 `> /dev/null`,以避免当您只关心它是否匹配时不必要地 grep 整个文件。 (2认同)