XARGS(1) | General Commands Manual | XARGS(1) |
xargs - 標準入力を読み込んでコマンドラインを作成し実行する
xargs [options] [command [initial-arguments]]
このマニュアルページは GNU 版 xargs の使用法を説明しています。 xargs は、 標準入力から空白や改行で区切られた一連の項目を読み込み (空白はダブルクォート、 シングルクォート、 バックスラッシュによって保護できます)、 これを引数にして、 指定した command を 1 回以上実行する (デフォルトのコマンドは echo です)。 このとき、 ユーザーが command に対して指定した引数 (上記書式の initial-arguments) があれば、 標準入力から読み込んだ一連の項目は、 その後ろに追加されます。 標準入力における空行は無視されます。
command のコマンドラインは、 (-n や -L オプションが使用されていない場合は) システムが定めているコマンドラインの長さの限界に達するまで、 長いものが作成されます。 そして、 指定された command が、 入力項目のリストを一つ残らず処理するのに必要な回数だけ、 呼び出されます。そのため、おおむね、 command が呼び出される回数は、入力項目の数よりも、ずっと少なくてすむことになります。 このことは、たいていの場合、パフォーマンスを著しく向上させることになります。 なお、コマンドの中には、都合がよいことに、並列的に実行できるものもあります。-P オプションを参照してください。
Unix では、 ファイル名に空白や改行を含むことが可能なので、 こうしたデフォルトの動作は、 しばしば問題となります。 空白や改行を含むファイル名は、 xargs によって適切に処理されません。 このような状況では、 -0 オプションの利用をお勧めします。 これを用いれば問題を回避できます。 なお、 -0 オプションを使う場合は、 xargs の入力を生成するプログラム側でも、 区切り文字にヌル文字を使うようにする必要があります。 たとえば GNU find を使う場合ば、 -print0 オプションを用いることになります。
指定したコマンドの実行が、 終了ステータス 255 で終了すると、 xargs は即座に停止して、 それ以上入力を読み込みません。 このときには、 エラーメッセージを標準エラーに出力します。
注意してほしいのは、 共有リソースに対する並列アクセスをきちんと管理するのは、 呼び出されるプロセス側の問題であるということです。 たとえば、 複数のプロセスが標準出力に書き出そうとした場合、 出力順は不定です (そして混じり合ってしまうことが多い)。 そうならないためには、 プロセス同士が何らかの形で協力し合う必要があります。 ロックスキーム (locking scheme) のようなものを使うのは、 そうした問題を避けるための一方法です。 ただ一般にロックスキームを使っても、 出力順は適切に保証してくれるものの、 パフォーマンスは低下します。 パフォーマンスが落ちるのが嫌ならば、 単純に各プロセスがそれぞれ別の出力ファイルを作るように (あるいは別のリソースを使うように) すればよいでしょう。
オプション --max-lines (-L, -l)、 --replace (-I, -i)、 --max-args (-n) は同時に指定することはできません。これらを同時に指定した場合、 通常 xargs は、 コマンド行上の最後に指定されたオプションを利用します。つまり誤って指定された (最終分よりも前に指定された) オプション値はデフォルトにリセットされます。さらに xargs は警告情報を stderr に出力します。この仕様には例外があり、 max-args に対して特別な値 1 ('-n1') を指定した場合、 --replace オプションおよびその別名である -I と -i の後ろであれば、 max-args は無視されます。これは相反する指定にならないからです。
find /tmp -name core -type f -print | xargs /bin/rm -f
/tmp ディレクトリ以下に core という名前のファイルを探して、 それを消去します。 改行や空白を含むファイル名があると、 正しく動作しないので、注意してください。
find /tmp -name core -type f -print0 | xargs -0 /bin/rm -f
/tmp ディレクトリ以下に core という名前のファイルを探して、 それを消去します。 ファイル名の処理に当たっては、 ファイル名やディレクトリ名に空白や改行が含まれていても、 適切に扱われるようにしています。
find /tmp -depth -name core -type f -delete
/tmp ディレクトリ以下に core という名前のファイルを探して、 それを消去します。 上の例よりもこちらの方が効率的です (なぜなら、 rm を実行するために fork(2) と exec(2) を使わないですみますし、 そもそも、 xargs のプロセスを必要としないからです)。
cut -d: -f1 < /etc/passwd | sort | xargs echoシステムの全ユーザーを列挙した簡潔なリストを生成します。
xargs の終了ステータスは以下のとおりです。
128 以上の終了ステータスは、 致命的なシグナルのせいでプログラムが止まったことを示すために、 シェルが使用しています。
GNU xargs version 4.2.9 以来、 ファイルの論理的な終端を示す指標 (a logical end-of-file marker) を持たないのが、 xargs のデフォルトになっています。このことは POSIX (IEEE Std 1003.1, 2004 Edition) で認められています。
-l や -i オプションは 1997 年版の POSIX 規格には存在するが、 2004 年版の POSIX 規格には存在しません。従って、 それぞれ -L や -I の方を使うべきです。
-o オプションは POSIX 規格を拡張したものであり、 BSD と互換性を図るためのものです。
POSIX 規格は、 実装に当たって、 exec 関数に対する引数のサイズに上限を設けることを認めています。 そして、 その上限は、 環境のサイズも含めて、 少なくとも 4096 バイトあればよいことになっています。 移植性のあるスクリプトを書こうと思ったら、 これより大きいサイズを当てにしてはいけません。 もっとも、 実際の上限がそんなに小さい実装に、 筆者は出会ったことはありません。 --show-limits オプションを使えば、 使用中のシステムで有効な実際の上限を知ることができます。
xargs を安全に使うことはできません。 なぜなら、 入力ファイルの一覧を作成する時間と、 xargs からの実行コマンドがその一覧を使用する時間との間に、 必ず差が発生するためです。 仮に、 他のユーザーがすでにシステムにアクセスしていたとして、 そのユーザーが、 その一瞬の隙にファイルシステムを操作して、 xargs が実行するコマンドの動作を、 こちらが意図していないファイルに無理矢理向けてしまう、 といったことができてしまいます。この議論や、 これに関連する問題については、 findutils に含まれる Texinfo 文書の「Security Considerations」という章でもっと細かく述べているので、 参照してください。 なお、 find の -execdir オプションは、 より安全な方法として xargs の代わりに利用されることがよくあります。
-I オプションを使うと、 標準入力から読み込まれた各行が、 内部的にバッファに保存されます。 つまり、 -I オプションをつけたときに、 xargs が受けつける入力 1 行には、 長さの上限があるということです。 この制限を回避するには、 -s オプションを使って、 xargs が使用するバッファ領域のサイズを増やして対処します。 もう 1 つの xargs を追加で実行すれば、 極端に長い行が発生しないようにできます。たとえば以下です。
somecommand | xargs -s 50000 echo | xargs -I '{}' -s 100000 rm '{}'
xargs の 1 つめの呼び出しでは、 入力行の長さに上限はありません。 これは -I オプションを使っていないからです。 xargs の 2 つめの呼び出しには、 上限設定がありますが、 処理できなくなるような 1 行は、 入ってこないのが明らかです。こうすることが理想的な解決法というわけではありません。 それよりも、 -I オプションが長さの制限を設けないでいる方が望ましいことです。 だからこそ、 この問題を「バグ」セクションで説明しているわけです。 なおこの問題は、 find(1) の出力では発生しません。 find は 1 行に 1 ファイル名しか出力しないためです。
GNU findutils
オンラインヘルプ:
<https://www.gnu.org/software/findutils/#get-help>
翻訳に関するバグ報告
<https://translationproject.org/team/>
その他の問題について GNU Savannah バグトラッカー経由での報告:
Copyright © 1990-2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
<https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it. There is NO
WARRANTY, to the extent permitted by law.
find(1), kill(1), locate(1), updatedb(1), fork(2), execvp(3), locatedb(5), signal(7)
完全なドキュメント
<https://www.gnu.org/software/findutils/xargs>
またローカルにおいては
info xargs
により参照できます。