xargsの各オプションにおける引数の渡され方

普段xargsをよく使っているが、いつも -I オプションで引数をループさせる用途であることがほとんどなので、xargsはループ用のコマンドだと思いこんでいた。そのため先日、別の人のシェルスクリプトを読んだときに混乱してしまったのでまとめておく。

オプションなし

そもそもxargsは、標準入力として受け取ったデータをパラメータとして別のコマンドに渡すためのもの。ここでいうパラメータとは、標準入力を空白文字・改行の両方で区切ったものを指す。
デフォルトでは、xargsは受け取った全てのパラメータを1つのコマンドに対する引数として渡す。そのため、xargs以降に指定したコマンドは1回のみ実行される。

echo hoge fuga\\npiyo | xargs echo
hoge fuga piyo # echo hoge fuga piyoが実行された

-I オプション

-I オプションを使うと、標準入力が改行で分割され、コマンド1回の実行につき1行ずつ使用される。そのため、xargs以降に指定したコマンドは、標準入力の行の数だけ実行されるようになる。使い所が多く便利。
for ループとの違いは、引数が1つ渡されるたびにxargs以降のコマンドが実行されること。 for ループの場合、for i in... の部分のコマンドがすべて終了し、繰り返される要素がすべて揃って始めて for ループ内部のコマンドが実行される。

echo hoge fuga\\npiyo | xargs -I {} echo {}
hoge fuga # echo hoge fugaが実行された
piyo # echo piyoが実行された

-n オプション

-n コマンドは、xargs以降に指定したコマンドが、最大いくつのパラメータを使えるかを指定するもの。例えば -n 1 と指定すると、パラメータが1つずつ渡され、xargs以降に指定したコマンドはパラメータの数だけ実行される。 -n 1 の場合、 -I の場合よりもさらに細かい単位で分割されることに注意。

echo hoge fuga\\npiyo | xargs -n 1 echo    
hoge # echo hogeが実行された
fuga # echo fugaが実行された
piyo # echo piyoが実行された