为什么在 GNU xargs 中与“-0”一起使用时,“-r”似乎被忽略了?

为什么在 GNU xargs 中与“-0”一起使用时,“-r”似乎被忽略了?

打印带有换行符、xargs调用和其他内容的常规情况:printf

>>printf "foo\n" | xargs -r printf "->%s\n"
->foo
>>

如果使用空输入,则根本-rxargs调用该命令:

>>printf "\n" | xargs -r printf "->%s\n"
>>

使用空值而不是换行符,如果有输入,一切都是一样的xargs

>>printf "foo\0" | xargs -r -0 printf "->%s\n"
->foo
>>

但如果没有输入,无论如何都会打印一些内容:

>>printf "\0" | xargs -r -0 printf "->%s\n"
->
>>

所以,要么

  • 我错过了一些东西(什么?)

  • 与(但哪个)-r一起使用时有一些充分的理由可以忽略?-0

  • 我的(findutils 4.6.0.225-235f)中有一个错误,xargs但很难决定:

    • 我在另外两个实例中发现了相同的行为(Ubuntu 16.04 上的 4.7.0-git 和 Windows 上的另一个 4.6.0),
    • 我不敢相信这种事情可以通过回归测试。
    • 另一方面这个问题意味着它可以在过去发挥作用

那么, 的真正预期行为是什么xargs

答案1

xargs -r cmd跳过cmd不带参数的运行。

使用 时-0,会为输入上的每个 NUL 分隔记录创建一个参数

printf '\0' | xargs -r0 cmd

您正在输入一条空记录,因此cmd使用一个空参数进行调用(并且使用printf '\0\0',这将是 2 个空记录,等等)。

和:

printf '' | xargs -r0 cmd

您没有提供任何记录,因此cmd不会运行。

和:

printf '' | xargs -0 cmd

您仍然没有提供任何记录,但因为-r没有提供,cmd仍然会被调用一次而不带参数。

without -0,xargs需要一个非常特殊的输入格式,它不是像 withxargs -0或那样的简单分隔列表xargs -d '\n'

为了提供一个空的参数,你需要类似的东西:

printf '""\n' | xargs -r cmd
printf "''\n" | xargs -r cmd

或者就此而言:

printf '\n\n \t\t "" \n\n \t\n' | xargs -r cmd

printf -- '-%s\n'不是测试该命令的最佳选择,因为它在不传递任何参数时提供与传递一个空参数时相同的输出。

更好的可能是:

$ printf '\n\n \t\t "" \n\n \t\n' | xargs -r zsh -c 'PS4=Got; set -x; : "$@"' zsh
Got: ''
$ printf '\n\n \t\t \n\n \t\n' | xargs zsh -c 'PS4=Got; set -x; : "$@"' zsh
Got:
$ printf '\t\n\n' | xargs -rd '\n' zsh -c 'PS4=Got; set -x; : "$@"' zsh
Got: $'\t' ''

或者:

$ printf '\t\n\0\0' | xargs -0 zsh -c 'print -rl $#: " - ${(q+)^@}"' zsh
2:
 - $'\t\n'
 - ''

相关内容