2

如果我有一个文件列表,其中一些文件的名称中有空格,生成自,例如:

find . -iname "*hs" | grep foo

如何将它们作为参数传递给单个进程,例如process name1 name2 ...

请注意,我想将所有文件名作为单独的参数传递给单个进程,因此标准for f in *解决方案不起作用

4

1 回答 1

5
find . -iname "*hs*" -exec grep foo {} +

find . -iname "*hs*" -print0 | xargs -0 grep foo

两者都有效;第一个甚至可能更有效,除非该+选项将更少的文件组合到命令行xargs中。

如果您通过 shell globbing 生成文件名,则:

grep foo *hs*

保留文件名中的间距。用于ls生成名称是非常有问题的。


过滤名称

grep 命令旨在在批量处理之前过滤文件名列表,而不是搜索文件本身的内容。

所以你想要同时匹配' hs '和' foo '的名字?在这种情况下,你最好find还是使用:

find . \( -iname "*hs*" -a -iname "*foo*" \) -exec grep foo {} +

使用find.

GNUgrep扩展-Z-z

如果你不能这样做(你的grep正则表达式需要太复杂find),那么你就会遇到困难,除非你有一个(假设的?)版本grep,它将读取由空值分隔的“行”。

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

这几乎是我们想要的,但不完全是。POSIX 2008getdelim()函数将是使用的工具;为此目的添加一个-z选项grep,然后grep -lzZ ....在将find ... -print0数据馈送到xargs -0.

上面的引用来自 Mac OS X 10.7.5 的手册页,GNUgrep是 2.5.1 版。也许更新版本的 GNUgrep可以更好地提供帮助?

你瞧,GNU grep2.14 支持必要的选项:

-z,--null-data
将输入视为一组行,每行都以零字节(ASCII NUL 字符)而不是换行符结尾。与-Zor--null选项一样,此选项可以与 'sort -z' 之类的命令一起使用,以处理任意文件名。

从运行脚本find

另一个不容忽视的选项是创建一个由find命令运行的脚本:

find . -iname "*hs*" -exec ./list-foo + 

list-foo脚本可能在哪里:

for arg in "$@"
do
    case "$arg" in
    (*foo*) echo "$arg";;   # This will still cause problems
    esac
done

这标识了文件;这echo是次优的。也许您需要捕获数组中的名称,然后使用数组调用最终命令:

array=( )
i=0
for arg in "$@"
do
    case "$arg" in
    (*foo*) array[$((i++))]="$arg";;
    esac
done

if [ "$i" -gt 0 ]
then real_work "${array[@]}"
fi

real_work真正起作用的程序(脚本?)在哪里。完成后你可以扔掉list-foo它,除非你要一遍又一遍地做同样的过滤工作。


包含空格的通配名称

您可以通过转义空格来全局包含空格的名称:

rm -i -- *\ *

这将扩展到名称中带有空格的文件名,这有助于清理文件名包含为测试此问题的答案而创建的文件的目录。

于 2013-02-05T03:32:29.057 回答