- xargsは、コマンドの出力を入力として別のコマンドに送信できるコマンドで、echo、rm、mkdirなどのコマンドが標準入力を引数として受け入れるようになります。
- xargsは、wcなどの他のコマンドと一緒に使用して、複数のファイルの単語、文字、行を簡単にカウントできます。
- xargsは、ファイルを複数の場所にコピーしたり、ネストされたディレクトリ内のファイルを削除したり、findコマンドを使用してアーカイブファイルを作成したりするために使用できます。
Linuxコマンドを連結する必要があるけれど、そのうちの一つがパイプ入力を受け付けない?そんなときはxargs
コマンドの出番です。
xargsコマンドを使用する理由
xargs
コマンドは、標準データストリームを使用して実行パイプラインを構築するために使用されます。つまり、xargs
を使用して、あるコマンドの出力を別のコマンドにパラメータとして送信できます。
標準Linuxユーティリティはすべて、3つのデータストリームに関連付けられています。それらは、標準入力ストリーム(stdin)、標準出力ストリーム(stdout)、標準エラーストリーム(stderr)です。xargs
を使用することで、echo
、rm
、mkdir
などのコマンドが標準入力を引数として受け入れられるようになります。
これらのストリームはテキストで動作します。テキストを使用してコマンドに入力(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
に処理を続行してもよいか確認を求めるプロンプトを表示させることができます。
ファイル名の文字列をxargs
でtouch
に渡すと、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 d
がfind
にファイルをではなくディレクトリを検索するように指示していることです。
削除されたディレクトリの名前が削除されるごとに表示されます。tree
で確認できます。
tree -d
すべてのネストされたサブディレクトリが削除されます。
1つのファイルタイプを除くすべてのファイルを削除する
find
、xargs
、rm
を使用して、保持したい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
は、情報を吐き出すことができるコマンドと、それを取り込むように構築されていないコマンドの間のギャップを埋めます。
xargs
とfind
の両方には膨大な数のオプションがあります。詳細については、manページを確認することをお勧めします。
コメントする