find 的 -print0 和 xargs 的 -0 开关是否有 grep 等效项?

人气:880 发布:2022-10-16 标签: unix bash grep find xargs

问题描述

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

I often want to write commands like this (in zsh, if it's relevant):

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

(或更复杂的 grep 组合)

(or more complex combinations of greps)

近年来find 增加了-print0 开关,xargs 增加了-0,允许处理文件中带有空格的文件以一种优雅的方式通过空终止文件名来命名,允许这样做:

In recent years find has added the -print0 switch, and xargs has added -0, which allow handling of files with spaces in the name in an elegant way by null-terminating filenames instead, allowing for this:

find <somebasedirectory> -print0 | xargs -0 dosomecommand

但是,grep(至少我拥有的版本,Ubuntu 上的 GNU grep 2.10)似乎没有等效于使用 和 生成以空值结尾的线条;它有 --null,但这似乎只与使用 grep 直接在文件中搜索时使用 -l 输出名称有关.

However, grep (at least the version I have, GNU grep 2.10 on Ubuntu), doesn't seem to have an equivalent to consume and generate null-terminated lines; it has --null, but that only seems related to using -l to output names when searching in files directly with grep.

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

Is there an equivalent option or combination of options I can use with grep? Alternatively, is there an easy and elegant way to express my pipe of commands simply using find's -regex, or perhaps Perl?

推荐答案

使用 GNU Grep 的 --null 标志

根据 GNU Grep 文档,您可以使用Output Line Prefix Control 处理ASCII NUL 字符,方法与find 和xargs 相同.

Use GNU Grep's --null Flag

According to the GNU Grep documentation, you can use Output Line Prefix Control to handle ASCII NUL characters the same way as find and xargs.

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

-Z --null Output a zero byte (the ASCII NUL character) instead of the character that normally follows a file name. For example, ‘grep -lZ’ outputs a zero byte after each file name instead of the usual newline. This option makes the output unambiguous, even in the presence of file names containing unusual characters like newlines. This option can be used with commands like ‘find -print0’, ‘perl -0’, ‘sort -z’, and ‘xargs -0’ to process arbitrary file names, even those that contain newline characters.

使用来自 GNU Coreutils 的 tr

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

Use tr from GNU Coreutils

As the OP correctly points out, this flag is most useful when handling filenames on input or output. In order to actually convert grep output to use NUL characters as line endings, you'd need to use a tool like sed or tr to transform each line of output. For example:

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

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

This pipeline will use NULs to separate filenames from find, and then convert newlines to NULs in the strings returned by egrep. This will pass NUL-terminated strings to the next command in the pipeline, which in this case is just xargs turning the output back into normal strings, but it could be anything you want.

754