使用空格作为批量参数的文件名

时间:2013-02-05 03:20:39

标签: file bash shell

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

find . -iname "*hs" | grep foo

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

请注意,我想将所有文件名作为单个参数传递给单个进程,因此标准for f in *解决方案无法正常工作

1 个答案:

答案 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的布尔功能。

GNU grep个分机-Z-z

如果你不能这样做(grep正则表达式需要对find来说过于复杂),那么除非你有一个(除非你有),否则你会遇到困难(假设的?grep版本将读取'行'由nulls分隔。

  

-Z--null
  输出一个零字节(ASCII NUL字符),而不是通常跟随a的字符   文件名。例如,grep -lZ在每个文件名之后输出一个零字节而不是   通常换行。即使存在文件名,此选项也会使输出明确无误   包含不正常的字符,如换行符。此选项可与命令一起使用   find -print0perl -0sort -zxargs -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 -- *\ *

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