Xargs

為什麼在 GNU xargs 中與 -0 一起使用時,-r 似乎被忽略了?

  • July 27, 2020

列印出帶有換行符、xargs呼叫和其他內容的正常情況:printf

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

使用空輸入代替,-r根本xargs不呼叫命令:

>>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什麼?

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所以仍然被呼叫一次而沒有參數。

沒有-0,xargs需要一個非常特殊的輸入格式,它不是一個簡單的分隔列表,如 with xargs -0orxargs -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'
- ''

引用自:https://unix.stackexchange.com/questions/600560