我正在寻找包含字符串" abc"的文件。在当前目录和所有子目录中:
grep abc **/*(.)
输出包含以下行:
...
Binary file test.pdf matches
...
是否可以在glob限定符中排除二进制文件?
编辑:这里使用grep
就是一个例子。我有兴趣通过zsh globbing限定符排除二进制文件,而不是在适当的grep选项中。
答案 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
中查找+cmd
和zshexpn(1)
。
没有任何设置:
ls **/*(.e:'file --mime $REPLY | grep -iqv binary':)
或使其不那么尴尬:
notbinary() { file --mime $REPLY | grep -iqv binary }
ls **/*(.+notbinary)