zsh glob限定符可以排除二进制文件

时间:2014-05-01 12:36:16

标签: zsh glob

我正在寻找包含字符串" abc"的文件。在当前目录和所有子目录中:

grep abc **/*(.)

输出包含以下行:

...
Binary file test.pdf matches
...

是否可以在glob限定符中排除二进制文件?

编辑:这里使用grep就是一个例子。我有兴趣通过zsh globbing限定符排除二进制文件,而不是在适当的grep选项中。

2 个答案:

答案 0 :(得分:5)

“二进制文件test.pdf匹配”消息不是由zsh打印,而是由grep本身打印。

原因是大部分时间,如果你打印包含模式的二进制文件的行,它会打印也打印“垃圾”(即不可打印的字符,真的很长的行等)。

在您的示例中,** / *(。)是zsh扩展。 您可以使用echo查看它扩展到的内容:

$ echo **/*(.)

请注意** / *(。)与顶部目录中带点的文件不匹配。

$ mkdir test
$ cd test
$ touch .mytest
$ echo  **/*(.)
zsh: no matches found: **/*(.)

现在,如果你想在当前目录中递归地找到包含某种模式的文件,那么这是一种非常简单的方法:

$ grep -rI .

如果要忽略当前目录中以点开头的文件:

$ grep -r *

关于使用zsh globbing过滤掉二进制文件。 这是zshexpn(1)的一部分:

A qualifier may be any one of the following:

   /      directories
   F      `full'  (i.e.  non-empty)  directories.  
   .      plain files
   @      symbolic links
   =      sockets
   (...)

请注意,虽然手册中说“普通文件”但并不意味着“纯文本文件”。 这意味着常规文件。

AFAIK,如果内容是二进制文件,则zsh无法选择基于文件的文件。

在使用globbing时,Zsh不读取文件内容,并将其与可用的文件系统元数据配合使用。

正因为如此,如果zsh实现了这个功能,那么整合时间会比目前可用的通用时间慢得多(当然,除非文件系统实现了一种“标记”二进制文件的方式,否则IMO不太可能)。

您可以尝试使用执行标志过滤掉文件,但这将非常不精确(即可执行脚本会出来,并且不可执行的二进制文件会进入)。

这个任务更适合grep本身,因为无论如何他都会阅读文件。

答案 1 :(得分:2)

您可以将任意代码作为glob限定符执行。在estring中查找+cmdzshexpn(1)

没有任何设置:

ls **/*(.e:'file --mime $REPLY | grep -iqv binary':)

或使其不那么尴尬:

notbinary() { file --mime $REPLY | grep -iqv binary }
ls **/*(.+notbinary)