xargsはいつ必要ですか?

xargsはいつ必要ですか?

このxargs命令はいつも私を混乱させます。一般的なルールがありますか?

次の 2 つの例を考えてみましょう。

$ \ls | grep Cases | less

「Cases」に一致するファイルを印刷しますが、コマンドを次に変更するには、次のものがtouch必要ですxargs

$ \ls | grep Cases | touch
touch: missing file operand
Try `touch --help' for more information.

$ \ls | grep Cases | xargs touch

答え1

違いは、ターゲットプログラムが許可するデータにあります。

パイプのみを使用すると、標準入力ストリーム(STDIN)のデータを生データの束として受け取り、一度に1行ずつ並べ替えることができます。ただし、一部のプログラムは標準入力のコマンドを受け入れず、そのコマンドの引数にそのコマンドが指定されることを期待しています。たとえば、touch次のようにコマンドラインからファイル名を引数として渡しますtouch file1.txt

ファイル名を出力するプログラムがある場合標準出力そしてそれらを使いたいパラメータとしてこれを行うには、それをtouch使用xargsしてSTDINストリームデータを読み取り、各行をコマンドの空白で区切られた引数に変換する必要があります。

これら2つは同じです。

# touch file1.txt
# echo file1.txt | xargs touch

xargsその機能が何であるか、なぜ必要なのかを正確に知らない限り、使用しないでください。多くのxargs場合、キャストを使用するよりも操作を実行するより良い方法があります。変換プロセスには、エスケープや単語拡張などの潜在的なトラップもあります。

答え2

すでに提供されている回答を拡張するには、xargs今日のマルチコアおよび分散コンピューティングの世界でますます重要になっている素晴らしい仕事を実行できます。つまり、ジョブを並列に処理できます。

たとえば、

$ find . -type f -name '*.wav' -print0 |xargs -0 -P 3 -n 1 flac -V8

*.wav => *.flac()をエンコードするために、3つのプロセスが同時に使用されます-P 3

答え3

xargsはstdinにファイルパスのリストがあり、それに対していくつかの操作を実行したい場合に特に便利です。たとえば、

$ git ls-files "*.tex" | xargs -n 1 sed -i "s/color/colour/g"

段階的に確認してみましょう。

$ git ls-files "*.tex"
tex/ch1/intro.tex
tex/ch1/motivation.tex
....

言い換えれば、入力は、どのようなタスクを実行したいパスのリストです。

echoこれらのパスに対してxargsが実行する操作を理解するには、次のようにコマンドを前に追加することをお勧めします。

$ git ls-files "*.tex" | xargs -n 1 echo sed -i "s/color/colour/g"
sed -i "s/color/colour/g" tex/ch1/intro.tex
sed -i "s/color/colour/g" tex/ch1/motivation.tex
....

この-n 1パラメータを使用すると、xargsは各行を独自のコマンドに変換します。このsed -i "s/color/colour/g"コマンドは、指定されたファイル内のすべての項目を置き換えますcolorcolour

これはパスにスペースがない場合にのみ機能します。これを行うには、nullで終わるパスをxargsへの入力として使用するようにフラグを渡す必要があります-0。使用例は次のとおりです。

$ git ls-files -z "*.tex" | xargs -0 -n 1 sed -i "s/color/colour/g"

上記と同じことを行いますが、いずれかのパスにスペースがある場合にも機能します。

findこれは、またはなど、ファイル名を出力として生成するすべてのコマンドに適用されますlocate。多くのファイルがあるgitリポジトリでこれを使用している場合は、次のようなgit grep -l代わりにこれを使用する方が効率的ですgit ls-files

$ git grep -l "color" "*.tex" | xargs -n 1 sed -i "s/color/colour/g"

このgit grep -l "color" "*.tex"コマンドは、「color」というフレーズを含む「* .tex」ファイルのリストを提供します。

答え4

xargsfindあなたの例では、必要な作業を正確に実行し、安全に実行するため、まったく使用する必要はありません。

使用したいものはまさに次のとおりですfind

find -maxdepth 1 -name '*Cases*' -exec touch {} +

この場合、-maxdepth 1これはサブディレクトリに深く入らず、現在のディレクトリでのみ検索することを意味します。 maxlengthに制限されない限り、findはデフォルトですべてのサブディレクトリを検索します(通常は必要なものです)。は{}その場所で置き換えられるファイルの名前であり、2+つのコマンド終了タグのうちの1つです。もう一つはです;。違いは;、各ファイルに対してコマンドを一度実行することで、次の+コマンドを実行することです。すべてのファイルを一度にコマンドします。ただし、シェルは自分で解釈しようとする可能性があるため、シェルを使用またはエスケープする必要があることに注意して;ください。はい、これらの小さな迷惑がたくさんありますが、その力はそれを相殺しても残ります。\;';'find

どちらも最初は学ぶのが難しいですfindxargs学習に役立つか、オプションを試してxargsください。このオプションは、実行するコマンドを表示し、実行するかどうかを尋ねるメッセージを表示します。-p--interactive

同様に、代わりにfindを使用してコマンドを実行するかどうかを尋ねるメッセージを表示することもできます。-ok-exec

しかし、時にはfindやりたいことをすべてすることができない場合がありますが、この時がxargs必要です。この-execコマンドは{}発生例を1つだけ許可するため、使用時にエラーが発生した場合はfind -type f -exec cp {} {}.bak \;次のことができます。find -type f -print0 | xargs -0 -l1 -IX cp X X.bak

以下について詳しく学ぶことができます。コマンドの実行内部にGNU Findutils マニュアル

また、ファイルを処理するときやオプションを使用したり、ヌル終了入力を生成したりしないと、find問題を引き起こす可能性があるスペースやその他の文字が発生するため、必要に応じて実行するのが安全であると述べました。内容が空です。xargs-0--null

関連情報