如果我有一个文件列表,其中一些文件的名称中有空格,例如:
find . -iname "*hs" | grep foo
如何将它们作为参数传递给process name1 name2 ...
等单个进程?
请注意,我想将所有文件名作为单个参数传递给单个进程,因此标准for f in *
解决方案无法正常工作
答案 0 :(得分: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
的布尔功能。
grep
个分机-Z
和-z
如果你不能这样做(grep
正则表达式需要对find
来说过于复杂),那么除非你有一个(除非你有),否则你会遇到困难(假设的?grep
版本将读取'行'由nulls分隔。
-Z
,--null
输出一个零字节(ASCII NUL字符),而不是通常跟随a的字符 文件名。例如,grep -lZ
在每个文件名之后输出一个零字节而不是 通常换行。即使存在文件名,此选项也会使输出明确无误 包含不正常的字符,如换行符。此选项可与命令一起使用find -print0
,perl -0
,sort -z
和xargs -0
处理任意文件名,甚至 包含换行符的那些。
这几乎是他们想要的,但并不完全。 POSIX 2008 getdelim()
函数将是使用的工具;为此目的向-z
添加grep
选项,然后使用grep -lzZ ....
过滤find ... -print0
数据,然后将其输入xargs -0
。
以上引用来自Mac OS X 10.7.5上的手册页,GNU grep
是2.5.1版。也许更新版本的GNU grep
能够提供更好的帮助吗?
瞧,GNU grep
2.14支持必要的选项:
-z
,--null-data
将输入视为一组行,每行以零字节(ASCII NUL字符)而不是换行符结束。与-Z
或--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 -- *\ *
这会扩展为名称中带有空格的文件名,这有助于使用包含为测试此问题答案而创建的文件的文件名来清理目录。