Linuxでxargsコマンドを使用する方法

  • xargsは、コマンドの出力を入力として別のコマンドに送信できるコマンドで、echo、rm、mkdirなどのコマンドが標準入力を引数として受け入れるようになります。
  • xargsは、wcなどの他のコマンドと一緒に使用して、複数のファイルの単語、文字、行を簡単にカウントできます。
  • xargsは、ファイルを複数の場所にコピーしたり、ネストされたディレクトリ内のファイルを削除したり、findコマンドを使用してアーカイブファイルを作成したりするために使用できます。

Linuxコマンドを連結する必要があるけれど、そのうちの一つがパイプ入力を受け付けない?そんなときはxargsコマンドの出番です。

xargsコマンドを使用する理由

xargsコマンドは、標準データストリームを使用して実行パイプラインを構築するために使用されます。つまり、xargsを使用して、あるコマンドの出力を別のコマンドにパラメータとして送信できます。

標準Linuxユーティリティはすべて、3つのデータストリームに関連付けられています。それらは、標準入力ストリーム(stdin)、標準出力ストリーム(stdout)、標準エラーストリーム(stderr)です。xargsを使用することで、echormmkdirなどのコマンドが標準入力を引数として受け入れられるようになります。

これらのストリームはテキストで動作します。テキストを使用してコマンドに入力(stdin)を送信し、応答(stdout)はテキストとしてターミナルウィンドウに書き込まれます。エラーメッセージもテキストとしてターミナルウィンドウに書き込まれます(stderr)。

LinuxおよびUnix系オペレーティングシステムの優れた機能の1つは、あるコマンドのstdout出力を2番目のコマンドのstdin入力にパイプできることです。1番目のコマンドは、その出力がターミナルウィンドウに送信されないことを気にせず、2番目のコマンドは、その入力がキーボードから来ていないことを気にしません。

Linuxコマンドはすべて3つの標準ストリームを持っていますが、そのすべてが別のコマンドのstdoutをstdinへの入力として受け入れるわけではありません。つまり、それらにパイプで入力することはできません。

そこでxargsの出番です。xargsコマンドの便利な例をいくつか紹介しました。遠慮なくいくつかスキップしてください。これらの例は、必ずしも相互に関連しているわけではありません。

xargsコマンド

xargsはパイプ入力を受け入れます。ファイルからの入力を受け入れることもできます。xargsは、その入力を、一緒に動作するように指示されたコマンドのパラメータとして使用します。xargsに特定のコマンドと一緒に動作するように指示しない場合、デフォルトでechoを使用します。

それを利用して、xargsが複数行の入力からでも常に1行の出力のみを生成する方法を示すことができます。

ls-1(1行に1つのファイル)オプションを使用すると、ファイル名の単一列が得られます。

ls -1 ./*.sh

これにより、現在のディレクトリ内のシェルスクリプトファイルが一覧表示されます。

想定どおり、単一列が得られます。これをxargsでパイプ処理するとどうなりますか?

ls -1 ./*.sh | xargs

出力は1つの長いテキストストリームとしてターミナルウィンドウに書き込まれます。

この機能により、xargsが他のコマンドにパラメータを供給できるようになります。

wcでxargsを使用する

xargsを使用して、wcが複数のファイルの単語、文字、行を簡単にカウントするようにできます。

ls *.page | xargs wc

以下のような処理が行われます。

  • lsは*.pageファイルを一覧表示し、そのリストをxargsに渡します。
  • xargsはファイル名をwcに渡します。
  • wcは、コマンドラインパラメータとして受け取ったかのようにファイル名を扱います。

各ファイルの統計は、全体的な合計とともに表示されます。

確認付きでxargsを使用する

-p(対話型)オプションを使用すると、xargsに処理を続行してもよいか確認を求めるプロンプトを表示させることができます。

ファイル名の文字列をxargstouchに渡すと、touchはそれらのファイルを作成します。

echo 'one two three' | xargs -p touch

実行するコマンドが表示され、xargsは「y」または「Y」、または「n」または「N」と入力してEnterキーを押すまで待機します。

Enterキーを押すだけで「n」とみなされます。コマンドは「y」または「Y」と入力した場合にのみ実行されます。

「y」を押してEnterキーを押しました。lsを使用して、ファイルが作成されたことを確認できます。

ls one two three

複数のコマンドでxargsを使用する

-I(初期引数)オプションを使用することで、xargsで複数のコマンドを使用できます。

このオプションは「置換文字列」を定義します。コマンドラインに置換文字列のトークンが表示されるたびに、xargsに提供された値が挿入されます。

treeコマンドを使用して、現在のディレクトリからサブディレクトリを調べます。-d(ディレクトリ)オプションにより、treeはファイルを無視してディレクトリのみを報告します。

tree -d

「images」というサブディレクトリが1つあります。

「directories.txt」というファイルには、作成したいディレクトリの名前が含まれています。catを使用してその内容を確認できます。

cat directories.txt

これをxargsの入力データとして使用します。使用するコマンドは以下のとおりです。

cat directories.txt | xargs -I % sh -c 'echo %; mkdir %'

これは次のように分解されます。

  • cat directories.txt |: これにより、directrories.txtファイルの内容(すべての新しいディレクトリ名)がxargsにプッシュされます。
  • xargs -I %: これはトークン「%」で「置換文字列」を定義します。
  • sh -c: これは新しいサブシェルを開始します。-c(コマンド)は、シェルにコマンドラインからコマンドを読み取るように指示します。
  • 'echo %; mkdir %': それぞれの「%」トークンは、xargsによって渡されるディレクトリ名に置き換えられます。echoコマンドはディレクトリ名を出力し、mkdirコマンドはディレクトリを作成します。

ディレクトリが1つずつリストされます。

treeをもう一度使用して、ディレクトリが作成されたことを確認できます。

tree -d

複数の場所にファイルをコピーする

xargsを使用すると、1つのコマンドで複数の場所にファイルをコピーできます。

2つのディレクトリの名前をxargsに入力パラメータとしてパイプ処理します。xargsに、これらのパラメータの1つずつのみを、一緒に動作しているコマンドに渡すように指示します。

この場合、コマンドはcpです。したがって、その効果はcpを2回呼び出すことで、そのたびに2つのディレクトリの1つをコマンドラインパラメータとして使用します。これが起こることを可能にするxargsパラメータは-n(最大数)オプションです。これを1に設定します。

cp-v(詳細)オプションも使用しているため、何が起こっているかが報告されます。

echo ~/Backups/ ~/Documents/page-files/ | xargs -n 1 cp -v ./*.page

ファイルは2つのディレクトリにコピーされ、一度に1つのディレクトリがコピーされます。cpは各ファイルのコピーアクションを報告するため、それらが実行されていることがわかります。

ネストされたディレクトリ内のファイルを削除する

ファイル名にスペースや改行文字などの特殊文字が含まれている場合、xargsはそれらを正しく解釈できません。-0(NULL終端文字)オプションを使用することで、その問題を克服できます。これにより、xargsにNULL文字をファイル名の最終区切り文字として使用するように指示します。

この例ではfindを使用します。findには、ファイル名の空白や特殊文字を処理するための独自のオプションがあります。それは-print0(フルネーム、NULL文字)オプションです。

find . -name "*.png" -type f -print0 | xargs -0 rm -v -rf "{}"

これは次のように分解されます。

  • find . -name "*.png": findは、ファイル(type -f)である「*.png」と一致する名前を持つオブジェクトを「.」の現在のディレクトリから検索します。
  • -print0: 名前はNULL文字で終了し、スペースや特殊文字が処理されます。
  • xargs -0: xargsもファイル名をNULLで終了したものとみなすため、スペースや特殊文字が問題を引き起こすことはありません。
  • rm -v -rf "{}": rmは詳細で何が起こっているかを報告します(-v)。再帰的(-r)になり、ネストされたサブディレクトリを調べ、プロンプトなしでファイルを削除します(-f)。「{}」は各ファイル名に置き換えられます。

すべてのサブディレクトリが検索され、検索パターンに一致するファイルが削除されます。

ネストされたディレクトリを削除する

ネストされたサブディレクトリのセットを削除したいとします。treeを使用すると、それらを確認できます。

tree -d

find . -name "level_one" -type d printo | xargs -o rm -v -rf "{}"

このコマンドは、findを使用して現在のディレクトリ内で再帰的に検索します。検索対象は、「level_one」というディレクトリです。ディレクトリ名はxargsからrmに渡されます。

このコマンドと以前のコマンドの唯一の重要な変更点は、検索語が最上位ディレクトリの名前であり、-type dfindにファイルをではなくディレクトリを検索するように指示していることです。

削除されたディレクトリの名前が削除されるごとに表示されます。treeで確認できます。

tree -d

すべてのネストされたサブディレクトリが削除されます。

1つのファイルタイプを除くすべてのファイルを削除する

findxargsrmを使用して、保持したい1つのタイプを除くすべてのファイルを削除できます。少し直感的ではありませんが、削除したいファイルの名前ではなく、保持したいファイルの種類の名前を指定します。

-notオプションは、検索パターンに一致しないファイルの名前をfindに返すように指示します。xargs-I(初期引数)オプションをもう一度使用します。今回、定義する置換文字列トークンは「{}」です。これは、以前に生成した置換文字列トークンとまったく同じように動作します。これはたまたま「%」でした。

find . -type f -not - name "*.sh" -print0 | xargs -0 -I {} rm -v {}

lsで確認できます。ディレクトリに残っているファイルは、「*.sh」検索パターンに一致したファイルのみです。

ls -l

Xargsを使用してアーカイブファイルを作成する

findを使用してファイルを検索し、xargsからtarに渡して、アーカイブファイルを作成できます。

現在のディレクトリで検索します。検索パターンは「*.page」なので、「.page」ファイルを探します。

find ./ - name "*.page" -type f -print0 | xargs -0 -tar -cvzf page_files.tar.gz

アーカイブファイルが作成されると、ファイルが期待どおりにリストされます。

データメディエーター

何かを積み重ねる場合、足場が必要なことがあります。xargsは、情報を吐き出すことができるコマンドと、それを取り込むように構築されていないコマンドの間のギャップを埋めます。

xargsfindの両方には膨大な数のオプションがあります。詳細については、manページを確認することをお勧めします。