如果我有一个文件列表,其中一些文件的名称中有空格,这些文件是通过以下方式生成的:
find . -iname "*hs" | grep foo如何将它们作为参数传递给像process name1 name2 ...这样的单个进程
请注意,我希望将所有文件名作为单个参数传递给单个进程,因此标准的for f in *解决方案将不起作用
发布于 2013-02-05 11:32:29
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的布尔功能。
GNU grep扩展-Z和-z
如果你不能做到这一点(对于find来说,你的grep正则表达式需要太复杂),那么你就有麻烦了,除非你有一个(假设?)将读取以空值分隔的“行”的grep版本。
-Z,--null
输出一个零字节( ASCII NUL字符),而不是通常跟在文件名后面的字符。例如,grep -lZ在每个文件名后输出一个零字节,而不是通常的换行符。此选项使输出明确明确,即使文件名中包含不常见的字符,如换行符。此选项可与find -print0、perl -0、sort -z和xargs -0等命令一起使用,以处理任意文件名,甚至包括包含换行符的文件名。
这几乎就是我们想要的,但并不完全是。可以使用POSIX2008getdelim()函数;为此,向grep添加一个-z选项,然后使用grep -lzZ ....在将find ... -print0数据提供给xargs -0之前对其进行过滤。
上面的引用来自MacOSX10.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 -- *\ *这将扩展到名称中包含空格的文件名,这有助于清理包含为测试此问题的答案而创建的文件名的目录。
https://stackoverflow.com/questions/14699653
复制相似问题