xargsはEX-argsと読み、引数を組み合わせるという意味を持ちます。xargsコマンドは標準入力からリストファイルを読み込み、引数のコマンドラインにそのリストファイルのアイテムを渡して、実行することができます。
目次
- 1 xargsの使い方
- 2 xargsの利用例
- 2.1 標準入力からコマンドにアイテムを挿入し実行 (オプションなし)
- 2.2 挿入するアイテムの数を指定 (-nオプション)
- 2.3 読み取る行数を指定 (-Lオプション)
- 2.4 アイテムをコマンド末尾以外に挿入 (-Iオプション)
- 2.5 スペースが含まれるファイル名を扱う (-0,--nullオプション)
- 2.6 アイテムの区切り文字を変更 (-dオプション)
- 2.7 EOF文字列の設定 (-Eオプション)
- 2.8 標準入力の代わりにファイルを指定 (-aオプション)
- 2.9 実行したコマンドを表示 (-tオプション)
- 2.10 空の入力を実行しない (-rオプション)
- 2.11 コマンドを実行するかどうか問う (-pオプション)
- 2.12 並列実行 (-Pオプション)
- 3 xargsとshの組み合わせ
- 4 参考
xargsの使い方
xargsコマンドは、標準入力からコマンドの引数にしたいアイテムのリストを、xargsコマンドの引数には実行したいコマンドを入力して、実行します。アイテムのリストは、例えば、findコマンドが利用できます。
xargsコマンドは引数にした実行したいコマンドの末尾に、標準入力から読み込んだアイテムを挿入して、実行したいコマンドを実行していきます。追記するアイテムはオプションで指定しない限り、コマンドラインで制限されている文字数まで一行のコマンドとして挿入されます。
1 2 |
$find . | xargs . ./file2.txt ./file1.txt ./file3.txt |
また、どのようなコマンドが実行されているかは-tオプションで確認することが出来ます。
xargsコマンドで引数にするコマンドがない場合は、デフォルトとしてechoコマンドが実行されます。
1 2 3 |
$find . | xargs -t echo . ./file2.txt ./file1.txt ./file3.txt . ./file2.txt ./file1.txt ./file3.txt |
xargsコマンドで標準入力からのアイテムをひとつずつコマンド実行するには-nオプションを利用します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$find . | xargs -n 1 . ./file2.txt ./file1.txt ./file3.txt $ $find . | xargs -t -n 1 echo . . echo ./file2.txt ./file2.txt echo ./file1.txt ./file1.txt echo ./file3.txt ./file3.txt |
xargsの利用例
標準入力からコマンドにアイテムを挿入し実行
(オプションなし)
xargコマンドは、標準入力からファイルリストなどのリストファイルからアイテムを読み取り、xargsコマンドの引数になっているコマンドの末尾にアイテムを挿入して、実行します。ファイルリストは空白や改行で区切られている必要があります。
コマンド例はカレントディレクトリから下のディレクトリにあるすべてのテキストファイルを結合しています。
コマンド例
1 |
find . -name '*.txt' -type f | xargs cat |
ディレクトリの内容
1 2 3 4 5 6 7 8 9 |
$tree . ├── dir1 │ └── file1-dir1.txt ├── file1.txt ├── file2.txt └── file3.txt 1 directory, 4 files |
ファイルの内容
1 2 3 4 5 6 7 8 9 10 11 |
$cat file1.txt file1.txt content $ $cat file2.txt file2.txt content $ $cat file3.txt file3.txt content $ $cat dir1/file1-dir1.txt file1-dir1.txt content |
実行結果
1 2 3 4 |
file2.txt content file1-dir1.txt content file1.txt content file3.txt content |
コマンド例と実行結果
1 2 3 4 5 |
$find . -name '*.txt' -type f | sort | xargs cat file1-dir1.txt content file1.txt content file2.txt content file3.txt content |
挿入するアイテムの数を指定
(-nオプション)
-nオプションを用いることで、挿入するアイテムの数を指定することができます。空白が含まれるアイテムは、アイテムや空白を' 'や" "で囲んだり、'\ 'のようにバックスラッシュでエスケープして一つのアイテムにできます
コマンド例(1の場合)
1 |
xargs -n1 < itemlist.txt |
itemlist.txt
1 2 3 4 5 6 |
item1 item2 'item3 item4' "item5 item6" item7\ item8 item9 item10 |
実行結果
1 2 3 4 5 6 7 |
item1 item2 item3 item4 item5 item6 item7 item8 item9 item10 |
コマンド例(2の場合)
1 |
xargs -n2 < itemlist.txt |
実行結果
1 2 3 4 |
item1 item2 item3 item4 item5 item6 item7 item8 item9 item10 |
読み取る行数を指定
(-Lオプション)
-Lオプションは、標準入力から最大何行読み取るかどうか指定することができます。-nオプションとは違い、行をアイテムとしてコマンドに挿入することができます。
コマンド例(1の場合)
1 |
xargs -L1 < itemlist.txt |
itemlist.txt
1 2 3 4 5 6 |
item1 item2 'item3 item4' "item5 item6" item7\ item8 item9 item10 |
実行結果
1 2 3 4 5 6 |
item1 item2 item3 item4 item5 item6 item7 item8 item9 item10 |
コマンド例(2の場合)
1 |
xargs -L2 < itemlist.txt |
実行結果
1 2 3 |
item1 item2 item3 item4 item5 item6 item7 item8 item9 item10 |
アイテムをコマンド末尾以外に挿入
(-Iオプション)
-Iオプションは、文字列を指定して、xargs内のその文字列をアイテムに置き換えることが出来ます。この文字列の置き換えにより、標準入力から来るアイテムをコマンド末尾以外でも使用することが出来ます。また、使用する文字列はfindコマンドの-execの式を参考に'{}'を指定することが多いでしょう。
また、-Iオプションは、標準入力からの入力行を1行読み取り、コマンドラインの最大文字数制限を超えたら終了します。これは-L1オプションと-xオプションを意味しています。
コマンド例
1 |
xargs -I{} echo {} : {} < itemlist.txt |
itemlist.txt
1 2 3 4 5 6 |
item1 item2 'item3 item4' "item5 item6" item7\ item8 item9 item10 |
実行結果
1 2 3 4 5 6 |
item1 item2 : item1 item2 item3 item4 : item3 item4 item5 item6 : item5 item6 item7 item8 : item7 item8 item9 : item9 item10 : item10 |
これは、-Iと似たオプションになります。-iオプションで文字列を指定しない場合は、-I{}と同じ機能になります。
スペースが含まれるファイル名を扱う
(-0,--nullオプション)
-0オプションまたは--nullオプションは、標準入力からアイテムの区切り文字をヌル文字にすることができます。これは、findコマンドの-print0の式と合わせて使うことができ、スペースが含まれているファイル名を扱うことができます。
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
$ls -1 file.txt 'text file.txt' 'text file2.txt' $ $find . -type f -print0 | xargs -0 -n1 ./text file.txt ./file.txt ./text file2.txt $ $find . -type f -print0 | xargs -0 rm -v './text file.txt' を削除しました './file.txt' を削除しました './text file2.txt' を削除しました |
アイテムの区切り文字を変更
(-dオプション)
-dオプションは、標準入力のアイテムリストの区切り文字を変更することができます。子の区切り文字にはC言語のprintfで使う'\n'のような文字を利用することができます。
コマンド例
1 |
xargs -d'\n' -n1 < itemlist.txt |
itemlist.txt
1 2 3 4 5 6 |
item1 item2 'item3 item4' "item5 item6" item7\ item8 item9 item10 |
実行結果
1 2 3 4 5 6 |
item1 item2 'item3 item4' "item5 item6" item7\ item8 item9 item10 |
EOF文字列の設定
(-Eオプション)
-Eオプションはファイルの終わりを示す文字列を設定することができます。標準入力で指定した文字列が読み込まれた場合、その文字列以降の入力はすべて無視されます。
コマンド例
1 |
xargs -E'--eof--' -L1 < eof-testfile.txt |
eof-testfile.txt
1 2 3 4 5 6 7 |
item1 item2 item3 --eof-- item4 item5 item6 |
実行結果
1 2 3 |
item1 item2 item3 |
標準入力の代わりにファイルを指定
(-aオプション)
-aオプションは、xargsコマンドで標準入力を指定する代わりにファイルを指定することができます。
コマンド例
1 |
xargs -a itemlist.txt -n1 |
itemlist.txt
1 2 3 4 5 6 |
item1 item2 'item3 item4' "item5 item6" item7\ item8 item9 item10 |
実行結果
1 2 3 4 5 6 7 |
item1 item2 item3 item4 item5 item6 item7 item8 item9 item10 |
実行したコマンドを表示
(-tオプション)
-tオプションは、xargsコマンドで実行したコマンドを標準エラー出力に出力して表示することができます。
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$xargs -t -a itemlist.txt -n1 echo item1 item1 echo item2 item2 echo item3 item4 item3 item4 echo item5 item6 item5 item6 echo item7 item8 item7 item8 echo item9 item9 echo item10 item10 |
空の入力を実行しない
(-rオプション)
xargsコマンドはどんな入力でも必ず一回はコマンドを実行します。
1 2 3 4 |
$xargs -t < /dev/null echo $ |
-rオプションを入れることで空の入力時はコマンドを実行しないようにできます。
1 2 |
$xargs -r -t < /dev/null $ |
コマンドを実行するかどうか問う
(-pオプション)
-pオプションを用いると、コマンドを実行するときに、実行するかどうかをプロンプトで問い、'y'か'Y'で始まる入力をすると、コマンドが実行されます。
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 10 11 |
$xargs -p -n1 < itemlist.txt echo item1 ?...y item1 echo item2 ?...y item2 echo item3 item4 ?...n echo item5 item6 ?...n echo item7 item8 ?...y item7 item8 echo item9 ?...n echo item10 ?...n |
並列実行
(-Pオプション)
-Pオプションを用いると、指定した数でコマンドを並列実行することができます。コマンドの並列実行を行うと処理をより高速に行うができます。
-Pオプションで0を指定すると利用できるプロセッサの最大数で実行します。
利用できるプロセッサの数は例えば、nprocコマンドで確認することができます。
1 2 |
$nproc 4 |
4と表示されたので、4つのプロセッサが利用できることが確認できました。コマンド例では、4つのプロセッサでコマンドを実行します。
コマンド例と実行結果(並列実行した場合)
1 2 3 4 5 6 7 8 9 10 11 |
$ls fileaa fileab fileac filead $ $time find . -name 'file*' | xargs -P0 -n1 gzip -k real 0m25.668s user 1m18.600s sys 0m2.044s $ $ls fileaa fileaa.gz fileab fileab.gz fileac fileac.gz filead filead.gz |
コマンド例と実行結果(並列実行をしなかった場合)
1 2 3 4 5 6 7 8 |
$time find . -name 'file*' | xargs -n1 gzip -k real 2m12.189s user 2m6.688s sys 0m2.556s $ $ls fileaa fileaa.gz fileab fileab.gz fileac fileac.gz filead filead.gz |
処理速度を向上できたかどうかを簡単な時間測定で処理時間を確認してみます。上の例は同じファイルの圧縮時間を計測したものになります。上の例で並列実行した場合の処理時間は約26秒で、並列実行をしなかった場合の処理時間は約132秒になりました。
132÷26=5.0769...で、並列実行をした結果、並列実行をしなかった場合と比べて約5倍の処理速度の向上ができました。
コマンドによっては並列実行を行うことで処理時間を高速化できる場合があるので、試してみても良いかもしれません。
xargsとshの組み合わせ
xargsコマンドでは、シェルの組み込みコマンド等を利用できません。たとえば、宣言された変数を確認するbashの組み込みコマンドdeclareを利用すると
1 2 |
$xargs declare < /dev/null xargs: declare: No such file or directory |
declareというファイルやディレクトリはありませんとエラーメッセージが表示されます。
シェルの機能を用いるため、shコマンドやbashコマンド等の-cオプションを利用することができます。
パイプを利用
xargsコマンドで実行するコマンドにパイプの機能を用いたい場合は、shコマンド等を通して実行することで利用することができます。
1 2 3 4 5 6 7 |
$ls fileaa fileab fileac filead $ $find . -name 'file*' | xargs -P0 -n1 -I{} sh -c 'gzip -c {} > {}.gz' $ $ls fileaa fileaa.gz fileab fileab.gz fileac fileac.gz filead filead.gz |
viのようなプログラムを利用
viのようなプログラムを利用する場合は標準入力が/dev/ttyでなければなりません。
xargsで実行するコマンドが-oオプションが実装されているxargsコマンドの場合は
1 |
find . -type f | xargs -o vi |
で起動することができます。
-oオプションが実装されていない場合は、shコマンドを通して、
1 |
find . -type f | xargs sh -c 'vi "$@" < /dev/tty' |
のように実行することができます。
間違えて、viのようなコマンドをxargsでそのまま実行して、端末がおかしくなった場合は、
1 |
stty sane |
で端末を修正できます。