正しいとマークされているものを含め、このページの既存の回答はすべて間違っているようです。それは質問が曖昧に表現されているという事実に由来します。
概要: コマンドを「指定された入力行ごとに1回だけ」実行し、行全体(改行なし)を単一の引数としてコマンドに渡す場合、これはUNIX互換の最良の方法です。
... | tr '\n' '\0' | xargs -0 -n1 ...
GNUにxargs
は、を廃止できる便利な拡張機能がある場合とないtr
場合がありますが、OS Xやその他のUNIXシステムでは使用できません。
長い説明のために…
xargsを使用する際に考慮すべき2つの問題があります。
- 入力を「引数」に分割する方法。そして
- 一度に子コマンドを渡す引数の数。
xargsの動作をテストするには、それが実行された回数と引数の数を示すユーティリティが必要です。それを行うための標準的なユーティリティがあるかどうかはわかりませんが、bashで非常に簡単にコーディングできます。
#!/bin/bash
echo -n "-> "; for a in "$@"; do echo -n "\"$a\" "; done; echo
show
現在のディレクトリに保存して実行可能にすると、次のようになります。
$ ./show one two 'three and four'
-> "one" "two" "three and four"
さて、元の質問が本当に上記のポイント2に関するものである場合(私が思うに、数回読んだ後)、次のように読む必要があります(太字の変更):
与えられた入力の各引数に対してxargsにコマンドを正確に一度だけ実行させるにはどうすればよいですか?そのデフォルトの動作では、入力を引数に分割し、コマンドを可能な限り数回実行して、各インスタンスに複数の引数を渡します。
次に答えは -n 1
です。
xargsのデフォルトの動作を比較してみましょう。これは、入力を空白で分割し、コマンドを可能な限り数回呼び出します。
$ echo one two 'three and four' | xargs ./show
-> "one" "two" "three" "and" "four"
およびその動作-n 1
:
$ echo one two 'three and four' | xargs -n 1 ./show
-> "one"
-> "two"
-> "three"
-> "and"
-> "four"
一方、元の質問がポイント1に関するものだった場合、入力の分割と次のように読む必要があります(ここに来る多くの人がそうだと思うか、2つの問題を混同しているようです)。
xargsに、指定された入力行ごとに1つの引数を指定してコマンドを実行させるにはどうすればよいですか?そのデフォルトの動作は、空白の周りの行を分割することです。
それから答えはもっと微妙です。
-L 1
それは助けになるかもしれないと思う人もいるでしょうが、それは引数の解析を変更しないことがわかりました。入力行ごとに1回だけコマンドを実行し、その入力行にあるのと同じ数の引数を使用します。
$ echo $'one\ntwo\nthree and four' | xargs -L 1 ./show
-> "one"
-> "two"
-> "three" "and" "four"
それだけでなく、行が空白で終わる場合、次の行に追加されます。
$ echo $'one \ntwo\nthree and four' | xargs -L 1 ./show
-> "one" "two"
-> "three" "and" "four"
明らかに、-L
xargsが入力を引数に分割する方法を変更することではありません。
クロスプラットフォーム方式(GNU拡張を除く)でそうする唯一の引数は-0
、入力をNULバイトに分割することです。
次に、改行をNULに変換するだけですtr
。
$ echo $'one \ntwo\nthree and four' | tr '\n' '\0' | xargs -0 ./show
-> "one " "two" "three and four"
これで、引数の解析は、末尾の空白も含めて問題なく見えます。
最後に、この手法をと組み合わせると-n 1
、入力が何であっても、入力行ごとに1つのコマンドが実行されます。これは、元の質問を調べる別の方法となる場合があります(タイトルを指定すると、おそらく最も直感的です)。
$ echo $'one \ntwo\nthree and four' | tr '\n' '\0' | xargs -0 -n1 ./show
-> "one "
-> "two"
-> "three and four"
find /path -type f -delete
さらに効率的です:)