【问题标题】:Why would xargs split input on spaces and how to resolve it?为什么 xargs 会在空格上拆分输入以及如何解决它?
【发布时间】:2020-01-05 02:39:08
【问题描述】:

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

我发现只需 echoing 变量即可为每一行适当地添加空格,并为每一行添加一个换行符终止符。但是,当我将printfecho 转到xargs 时,我发现xargs 似乎也将每一行的输入都用空格分隔。我将用下面的例子用 cmets 来说明,包括我看到的结果:

# 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"'

【问题讨论】:

  • 如果您希望xargs 采用整行而不是在[:blank:] 字符类上拆分,则使用xargs -L 1。我邀请您阅读 xargs 的手册页以了解 -l[max-lines], --max-lines[=max-lines] 选项的说明。
  • "xargs 从标准输入读取项目,由空格(可以用双引号或单引号或反斜杠保护)或换行符分隔"

标签: bash grep find echo xargs


【解决方案1】:

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

在您的示例中 echo "$excluded_list" 可能看起来像保留 原始文件名,但不幸的是它不是。尝试插入两个或 路径名中出现更多连续的空格,看看会发生什么。
作为急救,您可以将$list 用双引号括起来为&lt;&lt;&lt; "$list",但它 只不过是一种临时补救措施。

解决方法是:

  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 的扩展,可能不适用于其他平台。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-08
    • 2014-04-30
    • 2012-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-12
    • 2020-02-22
    相关资源
    最近更新 更多