如何通过 .gz 文件递归 grep?

Ken*_*dor 162 grep compression search recursive files

我正在使用脚本定期下载将原始 .eml 压缩为 .gz 文件的 gmail 邮件。该脚本为每一天创建一个文件夹,然后将每条消息压缩到其自己的文件中。

我想要一种在这个档案中搜索“字符串”的方法。

单独的 Grep 似乎无法做到这一点。我也试过 SearchMonkey。

J. *_*ord 179

如果要在当前目录下的所有 .eml.gz 文件中递归 grep,可以使用:

find . -name \*.eml.gz -print0 | xargs -0 zgrep "STRING"
Run Code Online (Sandbox Code Playgroud)

您必须转义第一个,*以便 shell 不会解释它。-print0告诉 find 在它找到的每个文件后打印一个空字符;xargs -0从标准输入读取并在每个文件之后运行命令;zgrep像 一样工作grep,但首先解压缩文件。

  • '-print0' 和 '-0' 不是强制性的。xargs 默认使用 '\n'。 (3认同)
  • `zgrep` 实际上似乎比在未压缩文件上运行的 `grep` 更快。这一定是因为压缩文件可以从 HD 读取和解压缩比从 HD 读取未压缩文件更快。 (3认同)
  • 如果路径中可能有空格字符,它们是必要的;除了复杂性之外,没有其他理由不使用它们。 (2认同)
  • @JaimeM。`xargs` 默认使用 _blanks_(空格)。当然,文件中几乎从来没有换行符,但空格并非闻所未闻(即使大多数 UNIXy 类型对它们皱眉)。也就是说,您可以更轻松地简化而不用担心空格:`find 。-name '*.eml.gz' -exec zgrep "STRING" {} +` 这在每次启动 `xargs` 时获得相同数量的参数,以及 `-print0`/`-0` 的安全性,并且没有额外进程启动和管道的开销,而且相当简洁。`-exec` 和 `+` 是 POSIX 指定的,所以据我所知,它应该在大多数半最新的类 UNIX 系统上。 (2认同)

don*_*sti 81

这里有很多混乱,因为不只有一个zgrep. 我的系统上有两个版本,zgrepfromgzipzgrepfrom zutils。前者只是一个调用gzip -cdfq. 它不支持-r, --recursive开关。1
后者是一个c++程序,它支持-r, --recursive选项。
运行zgrep --version | head -n 1将显示其中哪一个(如果有)是默认值:

zgrep (gzip) 1.6
Run Code Online (Sandbox Code Playgroud)

是包装脚本,

zgrep (zutils) 1.3
Run Code Online (Sandbox Code Playgroud)

cpp可执行文件。
如果你有后者,你可以运行:

zgrep 'pattern' -r --format=gz /path/to/dir
Run Code Online (Sandbox Code Playgroud)

无论如何,正如建议的那样,find+zgrep将同样适用于以下任一版本zgrep

find /path/to/dir -name '*.gz' -exec zgrep -- 'pattern' {} +
Run Code Online (Sandbox Code Playgroud)

如果zgrep您的系统中缺少(极不可能),您可以尝试:

find /path/to/dir -name '*.gz' -exec sh -c 'gzip -cd "$0" | grep -- "pattern"' {} \;
Run Code Online (Sandbox Code Playgroud)

但有一个主要缺点:您不会知道匹配项在哪里,因为匹配行前没有文件名。


1:因为这会有问题


JJo*_*oao 9

ag是 的变体 grep,具有一些不错的额外功能。

  • 有压缩文件的 -z 选项,
  • 有许多 ack 功能。
  • 它很快

所以:

ag -r -z your-pattern-goes-here   folder
Run Code Online (Sandbox Code Playgroud)

如果没有安装,

apt-get install silversearcher-ag   (debian and friends)
yum install the_silver_searcher     (fedora)
brew install the_silver_searcher    (mac)
Run Code Online (Sandbox Code Playgroud)

  • 很棒的工具,但仍然存在一些问题 [1280](https://github.com/ggreer/the_silver_searcher/issues/1280) [1348](https://github.com/ggreer/the_silver_searcher/issues/1348)。现在它需要标志 `ag --search-binary -z "quick"` (2认同)

ter*_*don 5

单独递归很容易:

   -r, --recursive
          Read all files  under  each  directory,  recursively,  following
          symbolic  links  only  if they are on the command line.  This is
          equivalent to the -d recurse option.

   -R, --dereference-recursive
          Read all files under each directory,  recursively.   Follow  all
          symbolic links, unlike -r.
Run Code Online (Sandbox Code Playgroud)

但是,对于压缩文件,您需要以下内容:

shopt globstar 
for file in /path/to/directory/**/*gz; do zcat ""$file" | grep pattern; done
Run Code Online (Sandbox Code Playgroud)

path/to/directory 应该是包含每天子目录的父目录。


zgrep是显而易见的答案,但不幸的是,它不支持该-r标志。来自man zgrep

这些 grep 选项将导致 zgrep 以错误代码终止:(-[d rR zZ]|--di*|--exc*|--inc*|--rec*|--nu*)。


Nat*_*zoo 5

如果你的系统有 zgrep,你可以简单地

zgrep -irs your-pattern-goes-here the-folder-to-search-goes-here/

如果您的系统没有 zgrep,您可以使用find命令对每个文件运行 zcat 和 grep,如下所示:

find the-folder-to-search-goes-here/ -name '*.gz' \ -exec sh -c 'echo "Searching {}" ; zcat "{}" | grep your-pattern-goes-here ' \;

  • `zgrep` 出于某种原因不会采用 `-r` 标志。这是在`man zgrep` 中提到的(另见我的回答)。 (4认同)