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 は即座に停止して、 それ以上入力を読み込みません。 このときには、 エラーメッセージを標準エラーに出力します。

オプション

-0, --null
    入力される項目が、 ホワイトスペース (空白や改行) ではなく、 ヌル文字によって区切られます。 また、 クォートやバックスラッシュは、 特別な扱いをしません (つまり、 すべての文字がそのままに解釈されます)。 ファイル終端文字列は無効になり、 他の引数と同じように扱われます。 このオプションは、 入力される項目にホワイトスペース、 クォート、 バックスラッシュなどが含まれる可能性がある場合に、 役に立ちます。 GNU find の -print0 オプションは、 このモードに適した入力を生成します。

-a file, --arg-file=file
    入力項目を、 標準入力からではなく file から読み込みます。 デフォルトでは、 指定したコマンドが実行される際に、 標準入力が /dev/null に付け換えられますが、 このオプションを使用した場合は、 標準入力の付け換えが起こりません。

--delimiter=delim, -d delim
    入力される一連の項目が、 指定された文字によって区切られることになります。 指定される区切り文字は、 単一の文字でもよく、 \n のような C 言語式のエスケープ文字でも、 8 進数や 16 進数のエスケープコードでもかまいません。 8 進数や 16 進数のエスケープコードは、 printf コマンドの場合と同様に解釈されます。 マルチバイト文字には対応していません。 入力を処理する際、 クォートやバックスラッシュは特別扱いされません。 すなわち、 入力中のあらゆる文字が、 文字通りに解釈されます。 -d オプションを指定すると、 ファイル終端文字列は無効になり、 (xargs が作成するコマンドラインにおいて) 他の引数と同じように扱われます。 入力が、 項目を改行で区切っているだけのような単純な構成の場合には、 このオプションを使ってもよいですが、 ほとんどの場合、 なるべくなら、 xargs の --null を使うように、 出力側のプログラムを組み立てる方がよいです。

-E eof-str
    eof-str をファイル終端文字列として設定します。 ファイル終端文字列が入力中の 1 行として現れると、 それ以後の入力は無視されます。 -E も -e も指定しない場合、 ファイル終端文字列は使用されません。

-e[eof-str], --eof[=eof-str]
    このオプションは -E オプションの同義語です。-E の方を使ってください。 理由は、 そちらが POSIX に準拠しているのに対して、 こちらは準拠していないからです。 eof-str の部分が省略されると、 ファイル終端文字列が存在しないことになります。 -E も -e も指定しない場合、 ファイル終端文字列は使用されません。

-I replace-str
    initial-arguments 中で文字列 replace-str が現れるすべての箇所を、 標準入力から読み込んだ名前で置き換えます。 なお、 標準入力中にクォートされていない空白があっても、 それは入力項目の区切りにはなりません。 区切り文字は改行文字だけになります。 -x と -L 1 の指定を暗に含みます。

-i[replace-str], --replace[=replace-str]
    このオプションは、 replace-str が指定されていれば、 -Ireplace-str の同義である。引数 replace-str が省略されていれば、 -I{} と同じことになります。 このオプションは非推奨です。-I を使ってください。

-L max-lines
    1 コマンド行につき最大 max-lines 行の (空行ではない) 入力行を使用します。 入力行の行末に空白文字が付いていると、 その行は次の入力行に論理的に続いていることになります。 -x の指定を暗に含みます。

-l[max-lines], --max-lines[=max-lines]
    -L オプションの同義語です。-L とは違って、 max-lines という引数を指定するかどうかは任意です。引数 max-lines を指定しなかった場合は、 デフォルトの 1 が使用されます。POSIX 規格では -L の方を使うことになっているので、 -l オプションの使用はお勧めできません。

-n max-args, --max-args=max-args
    1 コマンド行につき最大 max-args 個の引数を使用します。 作成されたコマンドラインが、 コマンドライン長の上限を超過する場合は (-s オプション参照)、 max-args より少ない引数が使用されることになります。 ただし、 -x オプションが指定されているときは別で、 その場合は xargs が終了します。

-P max-procs, --max-procs=max-procs
    同時に実行するプロセスの最大数を max-procs にします。 デフォルトは 1 です。 max-procs が 0 ですと、 xargs はできるだけ多くのプロセスを同時に実行しようとします。 -P オプションには、 -n か -L オプションを併せて使用するべきです。そうしないと、 おそらく exec 関数がたった一回しか実行されないことになります。 xargs の実行中に、 そのプロセスに SIGUSR1 シグナルを送れば、 同時に実行するコマンドの数を増やすことができます。 また、 SIGUSR2 シグナルを送れば、 その数を減らすことができます。 ただし、 実装が決めている上限を越えて増やすことはできませんし (上限は --show-limits を使えばわかります)、 1 より少なくもできません。 xargs は、 実行しているコマンドを終了させるわけではありません。 実行数を減らすように命じられたときは、 単に現在実行中のコマンドが二つ以上終了するのを待ち、 それから別のコマンドを開始します。

    注意してほしいのは、 共有リソースに対する並列アクセスをきちんと管理するのは、 呼び出されるプロセス側の問題であるということです。 たとえば、 複数のプロセスが標準出力に書き出そうとした場合、 出力順は不定です (そして混じり合ってしまうことが多い)。 そうならないためには、 プロセス同士が何らかの形で協力し合う必要があります。 ロックスキーム (locking scheme) のようなものを使うのは、 そうした問題を避けるための一方法です。 ただ一般にロックスキームを使っても、 出力順は適切に保証してくれるものの、 パフォーマンスは低下します。 パフォーマンスが落ちるのが嫌ならば、 単純に各プロセスがそれぞれ別の出力ファイルを作るように (あるいは別のリソースを使うように) すればよいでしょう。

-o, --open-tty
    コマンド実行に先がけて、 子プロセスにおいて stdin を /dev/tty として再オープンします。これは xargs を使って対話型アプリケーションを実行する場合に有用です。

-p, --interactive
    コマンド行 1 行ごとに、 実行するかどうかをユーザーに尋ねるプロンプトを出し、 端末から 1 行読み込みます。コマンド行を実行するのは、 返答が `y' または `Y' で 始まるときだけです。自動的に -t が指定されます。

--process-slot-var=name
    複数の子プロセスを同時実行しているとき、 その各子プロセスで環境変数 name にユニークな値をセットします。値は、 子プロセスが終了すると、 再利用されます。この機能は、 たとえば、 初歩的な負荷分散スキームで利用できます。

-r, --no-run-if-empty
    標準入力に空白しか含まれていない場合は、 指定したコマンドを実行しません。 通常では、 入力が全くない場合でも、 コマンドが一回は実行されます。 このオプションは GNU 拡張です。

-s max-chars, --max-chars=max-chars
    1 コマンド行につき最大 max-chars の文字を使用します。 この文字数には、 指定したコマンドと initial-arguments、 それに各引数文字列の終端を示すヌル文字も含まれます。 指定できる値の上限は、 システム次第であり、 exec 関数に対する引数の最大長から、 現在の環境のサイズと 2048 バイトの余裕領域を引いたものです。もしその値が 128KiB 以上だったときは、 デフォルトの値には 128KiB が使用されます。 128KiB 未満のときは、 算出された上限がデフォルトの値になります。 1KiB は 1024 バイトです。制限がより厳しい場合でも、 xarg は自動的にそれに対応します。

--show-limits
    コマンド行の長さの上限を表示します。コマンド行長の上限は、 オペレーティングシステム、 xargs が設定したバッファサイズ、 それに -s オプションによって決まります。xargs にコマンドライン長の上限の表示以外をさせたくない場合は、 入力を /dev/null からパイプで xargs に渡してください (さらに --no-run-if-empty を指定した方がよいかもしれません)。

-t, --verbose
    実行する前に、 コマンドラインを標準エラー出力に表示します。

-x, --exit
    作成されたコマンド行がコマンド行長の上限を超過していたら (-s オプションを参照)、 終了します。

--help
    xargs のオプションについて簡単に説明し終了します。

--version
    xargs のバージョン番号を表示して、 終了します。

オプション --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 の終了ステータスは以下のとおりです。

    0   成功した。

    123 指定したコマンドの実行が 1-125 のステータスで終了した。

    124 指定したコマンドが 255 のステータスで終了した。

    125 指定したコマンドがシグナルによって kill された。

    126 指定したコマンドが実行できない。

    127 指定したコマンドが見つからない。

    1   上記以外のエラーが起きた。

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 バグトラッカー経由での報告:
    <https://savannah.gnu.org/bugs/?group=findutils>
GNU findutils パッケージのメーリングリスト bug-findutils において議論されている全般的なトピック:
    <https://lists.gnu.org/mailman/listinfo/bug-findutils>

著作権
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 により参照できます。