xargsコマンド
xargsの特徴
xargsコマンドは、空白や改行で区切られた一連の項目を読み込み、他のコマンドに引数として渡す。
コマンドが受け取ることができる引数の数やサイズには制限があり、大量の引数リストを受け付けられないことがある。そこでxargsは引数リストを分割して、コマンドに何回かに分けて引数を渡す。次の例はxargsが10個のファイル名を5個ずつwcコマンドに渡している。
find -name '*file*' -type f
(out)./file6.txt
(out)./file3.txt
(out)./file10.txt
(out)./file9.txt
(out)./file7.txt
(out)./file1.txt
(out)./file8.txt
(out)./file2.txt
(out)./file5.txt
(out)./file4.txt
find -name '*file*' -type f | xargs -t -r -L 5 wc
(out)wc ./file6.txt ./file3.txt ./file10.txt ./file9.txt ./file7.txt
(out) (wcの結果は省略)
(out)wc ./file1.txt ./file8.txt ./file2.txt ./file5.txt ./file4.txt
(out) (wcの結果は省略)
これがxargsの本質である、引数を拡張する(Extanded Arguments)挙動である。この例ではオプションで分割数を明示的に5にしているが、リストのサイズが大きければ自動で複数に分割する。seqコマンドで作成した大きなリストをxargsに渡す例を示す。
seq 100 | xargs | wc -l
(out)1
seq 100000 | xargs | wc -l
(out)5
xargsはコマンドが指定されなかった場合、リストを引数として展開した上で標準出力へ出力する。分割された場合は改行されるため、wcで改行の数を数えている。100行のリストであれば1回でコマンドにまとめて渡そうとするが、10000行のリストだと5回に分けてコマンドを実行しようとしていることがこの例から分かる。
xargsの使用例として、findコマンドで見つかったファイルの単語数を数えることを考える。単純にfindコマンドをパイプでwcコマンドに渡すと期待する結果とはならない。
find -name 'data?.txt'
(out)./data1.txt
(out)./data2.txt
find -name 'data?.txt' | wc
(out) 2 2 24
これはwcコマンドがカウントするファイルは引数で受け取る仕様だからである。標準入力から渡されたファイル名のリストはカウント対象の文章として認識されており、この2 2 24
というwcコマンドの出力は「./data1.txt(改行)./data2.txt」というテキストが、行数:2、単語数:2、バイト数:24であるということを意味している。
続いてxargsを使用することで、ファイルの単語数を数えられていることを示す。wcコマンドの引数としてファイル名が正しく渡されていることが分かる。
find -name 'data?.txt' | xargs -t -r wc
(out)wc ./data1.txt ./data2.txt
(out) 17 865 5899 ./data1.txt
(out) 13 659 4501 ./data2.txt
(out) 30 1524 10400 total
解説
xargsは入力をスペース(0x20),タブ文字(0x09),および改行文字(LinuxではLF)で分割し、引数として他のコマンドに渡す。引数の個数によっては複数回に分けてコマンドに渡すこともある。
コマンドラインオプション
オプション | 説明 |
---|---|
-a filename | 入力をファイルから受け取る。 |
-t | 実行するコマンドを表示する。 |
-p | 実行する前にユーザに確認する。自動で-tが有効になる。 |
-0 | 入力をヌル文字区切りとして扱う。 |
-d delimiter | 入力を指定の文字区切りとして扱う。 |
-I replace-str | 引数を展開する場所を指定する。 |
-L max-lines | コマンドに渡す引数の上限数を入力データの行数で指定する。 |
-n max-args | コマンドに渡す引数の上限数を指定する。 |
-P max-procs | 可能なら、プロセスを並列に実行する。(最大並行数はmax-procs) |
-r | 入力が空のとき、コマンドを実行しない。 |
使用例
しばしば他のコマンドの実行結果を、別のコマンドの引数として渡すために用いられる。
$ ls
(out)data1.txt data2.txt
ls | xargs -t -r wc
(out)wc data1.txt data2.txt
(out) 17 865 5899 data1.txt
(out) 13 659 4501 data2.txt
(out) 30 1524 10400 total
ファイルのリストに対してコマンドを実行する
lsの結果やfindの結果のようにストレージ上にあるファイルのリストを取得し、その結果に対してコマンドを実行する場合、findのexecオプションを使う方が良い。その方が空白を含むファイル名などがあった場合に安全である。
空白を含むファイル名に対して、wcを実行する例を示す。xargsはwc data file.txt
というコマンドを実行しており、これはdataとfile.txtの2つの単語数を数えるコマンドと解釈される。
ls
(out)'data file.txt'
ls | xargs -t -r wc
(out)wc data file.txt
(out)wc: data: No such file or directory
(out)wc: file.txt: No such file or directory
(out)0 0 0 total
findであれば、以下のようにすると動作する。
find -type f
(out)./data file.txt
find -mindepth 1 -execdir wc {} \;
(out) 1 6 27 ./data file.txt