我正在使用脚本定期下载我的gmail邮件,该邮件将原始.eml压缩为.gz文件。该脚本每天创建一个文件夹,然后将每条消息压缩到其自己的文件中。 >仅Grep似乎无法做到这一点。我也尝试过SearchMonkey。

评论

使用zgrep:zgrep-在压缩文件中搜索正则表达式

#1 楼

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

不解释它。 *告诉find在找到的每个文件之后打印一个空字符; -print0从标准输入读取并在每个文件之后运行命令; xargs -0的工作方式与zgrep相似,但首先将文件解压缩。

评论


“ -print0”和“ -0”不是必需的。 xargs默认使用'\ n'。

– Jaime M.
15年7月7日在8:50

如果路径中可能包含空格字符,则必须使用它们。除了复杂之外,没有其他理由不使用它们。

–丹尼尔·格里斯康(Daniel Griscom)
2015年9月23日14:38在

实际上,zgrep似乎比在未压缩文件上运行grep快。一定是因为压缩文件可以从HD读取并且比从HD读取未压缩文件更快地解压缩。

–老年病
16年8月19日在17:54



@JaimeM。 xargs默认使用空格(空格)。当然,文件中几乎永远不会包含换行符,但是空格并不是闻所未闻的(即使大多数UNIXy类型都不喜欢它们)。也就是说,您可以简化而不必担心空格:find。 -name'* .eml.gz'-exec zgrep“ STRING” {} +这样,每次启动xargs都会得到相同的参数,-print0 / -0的安全性,而所有这些都不会产生额外的进程启动和简洁明了。 -exec带有+是POSIX指定的,所以据我所知,它应该在大多数最新的类似UNIX的系统上。

–ShadowRanger
16 Dec 9'在18:38



@Jared是否有一种方法可以仅在知道文件模式的开头的情况下进行通配符搜索?例如,我有.gz文件,这些文件的末尾都有日期/时间戳。 ABCLog04_18_18_2_21.gz是否可以递归查找以ABC *开头的文件。我尝试在上面的示例中用ABCLog *替换\ *。eml.gz并得到有关文件格式的错误。:find:路径必须在表达式之前:ABCLog-2018-03-12-10-16-1.log.gz用法:查找[-H] [-L] [-P] [-Olevel] [-D help | tree | search | stat | rates | opt | exec] [path ...] [expression]

–开发人员
18-4-18在19:21



#2 楼

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

zgrep (gzip) 1.6


是包装脚本,

zgrep (zutils) 1.3


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

zgrep 'pattern' -r --format=gz /path/to/dir


无论如何,如所建议的,find + zgrep可以与zgrep的任何一个版本同样工作: />

如果系统中缺少zgrep(极不可能),则可以尝试以下方法:

find /path/to/dir -name '*.gz' -exec zgrep -- 'pattern' {} +


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


1:因为会出现问题

评论


如果zutils的zgrep不可用,则可以使用sudo apt-get install zutils将其安装在Ubuntu中。

–therealmarv
15年7月27日在1:46

从@therealmarv继续...然后Ubuntu将使用zutils zgrep而不是gzip之一。然后-r起作用!

–伊利亚·林恩(Elijah Lynn)
17 Mar 8 '17 at 22:08



有没有办法打印与之匹配的文件的行号?

–DogEatDog
17年11月8日在18:48

@DogEatDog-就像grep -n一样,zgrep -n将打印行号s。在手册中...

–don_crissti
17年11月9日在22:55



#3 楼

aggrep的变体,具有一些不错的附加功能。


具有-z选项用于压缩文件,
具有许多ack功能。
它很快

So:

ag -r -z your-pattern-goes-here   folder


如果未安装,

apt-get install silversearcher-ag   (debian and friends)
yum install the_silver_searcher     (fedora)
brew install the_silver_searcher    (mac)


评论


我得到ag:截断的文件:结果成功。我还应该添加其他标志吗?

–年
17年9月11日在21:10

很棒的工具,但是仍然有一些问题12801348。现在它需要标志ag --search-binary -z“ quick”

–hrvoj3e
20-4-15在7:22



#4 楼

单独进行递归很容易:

   -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.


但是,对于压缩文件,您需要类似以下内容:应该是包含每天子目录的父目录。


path/to/directory是显而易见的答案,但是不幸的是,它不支持zgrep标志。来自-r:这些


这些grep选项将导致zgrep终止,并显示错误代码:(-[drRzZ] | --di * | --exc * | --inc * |- -rec * | --nu *)。


#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 ' \;

评论


请原谅我这个问题……要搜索的文件有两层。 〜/ gmvault-db / db / 2015-02包含每个存档月份的文件夹,然后在该文件夹下存储该月份的.gz文件。如果我要在整个树中搜索.mil,那是我会做的吗?找到〜/ gmvault-db / db / -name'* .gz'\ -exec sh -c'echo“正在搜索{}”; zcat“ {}” | grep .mil'\;

–肯德尔
2015年3月2日在16:28



很好--irs中的“ r”将导致zgrep递归搜索。默认情况下,find命令以递归方式操作,因此任何以.gz结尾的文件都将被zcat并传递到grep中。 (并且{}将被扩展到将要搜索的文件的相对路径)。因此,当您获得成功时,将先搜索〜/ gmvault-db / db / 2015-02 / 03 / whatever.gz

–卡拉马祖的内特
2015年3月2日在16:29



这就是我得到的结果:查找:“路径必须在表达式之前:-exec”这是我使用的命令:查找〜/ gmvault-db / db / -name'* .gz'\ -exec sh -c'echo“ }”; zcat“ {}” | grep .mil'\;

–肯德尔
2015年3月2日在16:36

去掉'* .gz'和-exec之间的反斜杠。

–卡拉马祖的内特
15年3月2日在16:37

zgrep出于某种原因不会采用-r标志。那是在man zgrep中提到的(另请参见我的答案)。

– terdon♦
15年3月2日在17:12

#6 楼


xzgrep -l“ string” ./*/*.eml.gz


xzgrep是zgrep实用程序的派生类(/ bin / xzgrep更少)
从手册页:


xzgrep在可能未压缩或已用xz(1),lzma(1),gzip(1)压缩的文件上调用grep(1) ),bzip2(1)或lzop(1)。指定的所有
选项都直接传递到grep(1)。


-l打印匹配的文件名

-R递归将不起作用如脚本中明确禁止的那样,但是简单的shell globbing应该让我们到达那里。


./*/*.eml.gz


from相对路径,其中./today/sample.eml.gz在该实例的所有实例上都比我们在外壳中的相对位置低一级,并且以“ .eml.gz”结尾