54

我经常想写这样的命令(zsh如果相关,在 中):

find <somebasedirectory> | \
    grep stringinfilenamesIwant | \
    grep -v stringinfilesnamesIdont | \
    xargs dosomecommand

(或更复杂的 greps 组合)

近年来find添加了-print0开关,并且 xargs 添加了-0,它允许通过空终止文件名以优雅的方式处理名称中带有空格的文件,从而允许这样做:

find <somebasedirectory> -print0 | xargs -0 dosomecommand

但是,grep(至少我拥有的版本,Ubuntu 上的 GNU grep 2.10)似乎没有等效于使用生成空终止行的方法;它有--null,但这似乎只与使用-lgrep 直接在文件中搜索时使用输出名称有关。

是否有可以与 grep 一起使用的等效选项或选项组合?或者,是否有一种简单而优雅的方式来简单地使用 find-regex或 Perl 来表达我的命令管道?

4

6 回答 6

55

使用 GNU Grep 的--null标志

根据GNU Grep 文档,您可以使用输出行前缀控制来处理 ASCII NUL 字符,其方式与findxargs相同。

-Z
--null
输出一个零字节(ASCII NUL 字符)而不是通常跟在文件名后面的字符。例如,'grep -lZ' 在每个文件名之后输出一个零字节,而不是通常的换行符。此选项使输出明确,即使存在包含不寻常字符(如换行符)的文件名。此选项可与“find -print0”、“perl -0”、“sort -z”和“xargs -0”等命令一起使用,以处理任意文件名,即使是那些包含换行符的文件名。

tr从 GNU Coreutils使用

正如 OP 正确指出的那样,此标志在处理输入或输出的文件名时最有用。为了实际将 grep 输出转换为使用 NUL 字符作为行尾,您需要使用sedtr之类的工具来转换每一行输出。例如:

find /etc/passwd -print0 |
    xargs -0 egrep -Z 'root|www' |
    tr "\n" "\0" |
    xargs -0 -n1

此管道将使用 NUL 将文件名与find分开,然后将换行符转换为egrep返回的字符串中的 NUL 。这会将 NUL 终止的字符串传递给管道中的下一个命令,在这种情况下,这只是xargs将输出转换回正常字符串,但它可以是您想要的任何内容。

于 2013-04-13T14:57:19.527 回答
8

由于您已经在使用 GNU find,您可以使用其内部的正则表达式模式匹配功能来代替这些grep,例如:

find <somebasedirectory> -regex ".*stringinfilenamesIwant.*" ! -regex ".*stringinfilesnamesIdont.*" -exec dosomecommand {} + 
于 2013-04-12T19:43:45.050 回答
4

采用

find <somebasedirectory> -print0 | \
 grep -z stringinfilenamesIwant | \
 grep -zv stringinfilesnamesIdont | \
 xargs -0 dosomecommand

但是,该模式可能不包含换行符,请参阅错误报告

于 2016-11-11T11:37:59.027 回答
3

最新版本的 GNU grep 源代码现在可以使用-z/--null以空字符分隔输出,而它以前只能与 结合使用-l

http://git.savannah.gnu.org/cgit/grep.git/commit/?id=cce2fd5520bba35cf9b264de2f1b6131304f19d2

这意味着您的问题在使用最新版本时会自动解决。

于 2016-03-18T17:11:56.887 回答
2

-exec您可以将 find与+终止符一起使用,而不是使用管道。要将多个命令链接在一起,您可以在-exec.

find ./ -type f -exec bash -c 'grep "$@" | grep -v something | xargs dosomething' -- {} +
于 2013-04-12T16:37:45.993 回答
-3
find <somebasedirectory> -print0 | xargs -0 -I % grep something '%'
于 2013-07-17T20:03:03.720 回答