为什么xargs会在空格上拆分输入,以及如何解析它? [英] Why would xargs split input on spaces and how to resolve it?

查看:121
本文介绍了为什么xargs会在空格上拆分输入,以及如何解析它?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在以下 bash 脚本中,我正在从路径捕获文件列表到变量的文件列表,然后将其传递到 xargs 进行进一步的操作。

In the following bash script, I'm capturing file a file list from a path into a variable and then passing it on into xargs for further operations.

我发现只需 echo 变量即可适当地用空格换行,每行换行符终止。但是,当我 printf echo 转换为 xargs 时,我发现 xargs 似乎也将每行的输入用空格分开。我将在下面的示例中举例说明,并在注释中包含所看到的结果:

I've found that simply echoing the variable gives each line with spaces appropriately with a newline terminator for each line. However when I printf or echo this over to xargs, I'm finding that xargs appears to be splitting the input of each line by spaces as well. I'll illustrate with the following example with comments including the result I'm seeing:

# Using GNU find:
list="$( find '$SOME_PATH' -type f )"

excluded_list="$( egrep -v -f FILE_WITH_PATTERNS_OF_FOLDERS_TO_EXCLUDE <<< $list )"

# This prints out just fine with lines such as "/some/path/here with spaces" on their own line, eg:
#   /some/path/here with spaces
#   /another/path/here with spaces
#   /and yet another/path/here with spaces
echo "$excluded_list"

# But this prints out a line such as the above example "/some/path/here with spaces" broken up like this instead:
#   /some/path/here 
#   with 
#   spaces
#   /another/path/here 
#   with 
#   spaces
#   /and 
#   yet
#   another/path/here 
#   with 
#   spaces
printf "%s" "$excluded_list" | xargs -n 1 -P 1 sh -c 'echo "$0"'
# And the same result as `printf` above:
echo "$excluded_list" | xargs -n 1 -P 1 sh -c 'echo "$0"'


推荐答案

将多个文件名分配给单个变量
是一种反模式,因为除了空字节以外的任何特殊字符都可能出现在文件名
中,并且您不能再次将变量拆分为原始文件名。

It is an antipattern to assign multiple filenames into a single variable because any special character except for a null byte may appear in the filename and you cannot split the variable into original filenames again.

在您的示例中, echo $ excluded_list 可能看起来像保存
原始文件名,但不幸的是不是。尝试在路径名中再插入两个或
个连续的空格,看看会发生什么情况。

作为急救,您可以包装 $ list 用双引号作为<<< $ list ,但它只是一种临时补救措施。

In your example echo "$excluded_list" may look like preserving the original filenames but unfortunately it isn't. Try to insert two or more successive whitespaces in your pathname and see what happens.
As a first aid, you can wrap $list with double quotes as <<< "$list" but it is no more than a provisional remedy.

解决方法是:


  1. 将文件名存储在数组中

  2. 将空字节用作分隔符并通过管道处理结果

例如,您可以说:

while IFS= read -r -d "" f; do
    excluded_list+=("$f")
done < <(find "$SOME_PATH" -type f -print0 | egrep -v -z -Z -f FILE_WITH_PATTERNS_OF_FOLDERS_TO_EXCLUDE -)
for f in "${excluded_list[@]}"; do
    echo "$f"
done

find "$SOME_PATH" -type f -print0 | egrep -v -z -Z -f FILE_WITH_PATTERNS_OF_FOLDERS_TO_EXCLUDE - | xargs -0 -n 1 -P 1 sh -c 'echo "$0"'

请注意 -z -Z 选项是GNU grep的扩展,可能无法在其他平台上使用。

Note that -z and -Z options are GNU grep's extensions and may not work on other platform.

这篇关于为什么xargs会在空格上拆分输入,以及如何解析它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆