xargsは、Linuxで最も強力なコマンドの1つです。このチュートリアルでは、xargsを使用して標準入力をコマンドに変換する方法を説明します。
xargsコマンドとは何ですか?
xargsコマンドは、標準の入力または別のコマンドの出力からテキスト行を読み取り、それらをコマンドに変換して実行します。
多くの場合、findコマンドでxargsコマンドが使用されています。 findコマンドを使用すると、ファイル名のリストが表示され、xargsコマンドを使用すると、他のコマンドに入力されたかのように、それらのファイル名を1つずつ使用できます。
xargsはリダイレクションで機能するため、Linuxでのstdin、stdout、およびパイプリダイレクションに関する知識を磨くことを強くお勧めします。
xargsコマンドの使用方法
xargsコマンドの構文は次のとおりです。
xargs [options] [command [initial-arguments]]
しかし、おそらくそのように使用することはないでしょう。その力は、あるコマンドの出力を別のコマンドに結合することにあります。簡単な例で見てみましょう。
現在のディレクトリにはいくつかのテキストファイルがあり、flowers.txtにはこれらすべてのファイルの名前があります:
[email protected]:~/tutorial$ ls
flowers.txt lily.txt one_lotus.txt rose.txt three_lotus.txt two_lotus.txt
[email protected]:~/tutorial$ cat flowers.txt
lily.txt
one_lotus.txt
rose.txt
three_lotus.txt
two_lotus.txt
今の私の目的は、flowers.txtに記載されているすべてのファイルのファイルサイズを確認することです。常識では、catコマンドを組み合わせてすべてのファイル名を表示し、それをduコマンドにパイプしてファイルサイズを確認することができます。
ただし、直接パイプ処理すると、flowers.txtファイルに記載されている各ファイルのサイズはわかりません。
[email protected]:~/tutorial$ du -h
52K .
[email protected]:~/tutorial$ cat flowers.txt | du -h
52K .
なんで?まず、duコマンドは標準入力を取りません。次に、catコマンドの出力は個々のファイル名ではありません。改行文字で区切られた単語のようなものです。
xargsコマンドの魔法は、これと空白または新しい行で区切られたテキストを受け取り、それらを次のコマンドへの個別の入力に変換することです。
[email protected]:~/tutorial$ cat flowers.txt | xargs du -h
4.0K lily.txt
4.0K one_lotus.txt
16K rose.txt
4.0K three_lotus.txt
16K two_lotus.txt
これらのファイル名をduコマンドにフィードするのと同じと考えてください:
[email protected]:~/tutorial$ du -h lily.txt one_lotus.txt rose.txt three_lotus.txt two_lotus.txt
4.0K lily.txt
4.0K one_lotus.txt
16K rose.txt
4.0K three_lotus.txt
16K two_lotus.txt
xargsコマンドの威力に気づきましたね
xargsとfind:お互いのために作られました
多くの場合、「検索コマンド」と組み合わせて使用されていることがわかります。 findコマンドはファイルとディレクトリを検索し、それらの名前を返します。 xargsのおかげで、findコマンドの結果を、名前の変更、移動、削除などの特定の目的に使用できます。
たとえば、.txtで終わり、redという単語を含むすべてのファイルを取得するとします。 xargsを使用して、findコマンドとgrepコマンドを組み合わせることができます。
[email protected]:~/tutorial$ find . -type f -name "*.txt" | xargs grep -l red
./three_lotus.txt
./two_lotus.txt
./rose.txt
名前にスペースが含まれるファイルがあると、問題が発生します。 three_lotus.txtの名前を「threelotus.txt」に変更したとします。これで、xargsを介して処理されると、3つの2つの別々のファイルとlotus.txtとして表示されます。
[email protected]:~/tutorial$ find . -type f -name "*.txt" | xargs grep -l red
./two_lotus.txt
grep: ./three: No such file or directory
grep: lotus.txt: No such file or directory
./rose.txt
このような場合は、findコマンドの-print0オプションを使用する必要があります。改行文字ではなくASCIIヌル文字で行を区切ります。同様に、ASCII nullを受け入れるには、-0のxargsも使用する必要があります。
[email protected]:~/tutorial$ find . -type f -print0 -name "*.txt" | xargs -0 grep -l red
./two_lotus.txt
./three lotus.txt
./rose.txt
xargsを使用して実行されているコマンドを確認する場合は、-tオプションを使用できます。実行中の実際のコマンドを出力します。
[email protected]:~/tutorial$ find . -type f -name "*.txt" | xargs -t touch
touch ./three_lotus.txt ./two_lotus.txt ./lily.txt ./rose.txt
状況によっては、ファイルの削除など、特に注意が必要な場合があります。どのコマンドが実行されるかを確認し、実行を拒否するオプションがあるとよいでしょう。
xargsの-pオプションを使用して、プロンプトを表示できます。
[email protected]:~/tutorial$ find . -type f -name "*.txt" | xargs -p rm
rm ./three_lotus.txt ./two_lotus.txt ./lily.txt ./rose.txt ?...n
プレースホルダーとxargsを使用して、より詳細に制御する
デフォルトでは、xargsコマンドは、コマンドの最後に引数として標準入力を追加します。これは、最後の引数の前にそれを使用する必要がある場合に問題を引き起こします。
たとえば、moveコマンドを使用する場合は、最初にソースが必要で、次にターゲットが必要です。見つかったファイルをターゲットディレクトリに移動する場合、このコマンドは機能しません:
[email protected]:~/tutorial$ find . -type f -name "*.txt" | xargs -p mv new_dir
mv new_dir ./three_lotus.txt ./two_lotus.txt ./lily.txt ./rose.txt ?...y
mv: target './rose.txt' is not a directory
これは、オプション-I like this:
を使用してxargsでプレースホルダーを使用できる場所です。[email protected]:~/tutorial$ find . -type f -name "*.txt" | xargs -p -I {} mv {} new_dir
mv ./three_lotus.txt new_dir ?...n
mv ./two_lotus.txt new_dir ?...n
mv ./lily.txt new_dir ?...n
mv ./rose.txt new_dir ?...n
xargsがfindコマンドからすべてのファイル名を取得し、それを{}に保持するかのように考えてください。次に、mvコマンドに移動し、{}のコンテンツを提供します。
ここでの主な違いは、すべてのファイル名を同じコマンドに入れるのではなく、1つずつ追加することです。これが、引数ごとにmvコマンドが呼び出される理由です(上記の例でわかるように)。
注:プレースホルダーとして{}を使用しました。他のほとんどの文字や文字をプレースホルダーとして使用できます。 {}は安全な賭けであり、理解と区別が容易です。
xargsを使用して複数のコマンドを実行する
プレースホルダーを使用して、xargsで複数のコマンドを実行できます。
[email protected]:~/tutorial$ find . -type f -name "*.txt" | xargs -I {} sh -c 'ls -l {}; du -h {}'
-rw-rw-r-- 1 abhishek abhishek 0 May 28 17:02 ./three_lotus.txt
0 ./three_lotus.txt
-rw-rw-r-- 1 abhishek abhishek 0 May 28 17:02 ./two_lotus.txt
0 ./two_lotus.txt
-rw-rw-r-- 1 abhishek abhishek 0 May 28 17:02 ./lily.txt
0 ./lily.txt
-rw-rw-r-- 1 abhishek abhishek 0 May 28 17:02 ./rose.txt
0 ./rose.txt
プレースホルダーは次のパイプリダイレクトやその他のコマンドには拡張されないことに注意してください。これが、ここでshコマンドを使用した理由です。
ここでの例では、主にfind with xargsコマンドを使用しました。これが、最もよく表示されるコマンドだからです。ただし、xargsがfindコマンドでのみ使用できるように制限されているわけではありません。 xargsコマンドのそのような実用的な例の1つは、実行中のすべてのDockerコンテナーを停止する場合です。
docker ps -q | xargs docker stop
他のほとんどのLinuxコマンドと同様に、xargsにはさらに多くのオプションがあります。詳細については、xargsコマンドのマニュアルページをいつでも参照できます。
ここにリストされているxargsコマンドの例は、このすばらしいコマンドを十分に理解するのに十分だと思います。
ご質問やご提案がございましたら、コメント欄でお知らせください。