xargs の理解

シェルスクリプトで、パイプの後に xargs を使って処理を行うことがあります。
あまりこの使い方がピンと来ていなかったのですが、改めて man を読むとポイントは2つかなと思いました。

xargs とは

xargs は、 man によると “xargs – 標準入力を読み込んでコマンドラインを作成し、それを実行する” とあります。

ここから、以下の2つがポイントになります。

  • 標準入力を読み込む→パイプが有用
  • コマンドラインを作成する→コマンドの引数となる

xargs の基本形

xargs は以下のように使うことになります。

(コマンド1) | xargs コマンド2 

これだと分かりづらいので、例を挙げます。

拡張子 .tmp がついているファイルを見つけて、削除したいとします。

まず、 カレントディレクトリ以下に、 “.tmp” がついているファイルは以下で見つけることができます。

find . -name '*.tmp'

この結果を削除したいとします。

この時、

rm (findの結果)

とすれば消せるわけです。

そこで、xargsを使うと、rm の後に、パイプ前の find の結果を引数として渡してあげることができます。

find . -name '*.tmp' | xargs rm

引数を明示しなければいけない場合

引数を明示するのは、コマンドが複数の引数をとる場合です。
たとえば、 cp は2つの引数をとります。
今、find の結果を、temp というディレクトリにコピーしたい場合は、 ” -I {}” で
標準入力から受け取った各行を {} という記号で置き換えることを指定し、実際に引数に入るところに {} を置きます。

つまり、以下のようになります。

find . -name '*.tmp' | xargs -I {} cp -r {} temp

ちなみに、find の場合は xargs を使わなかったとしても、

find . -name '*.tmp' -exec rm {} \;
find . -name '*.tmp' -exec cp {} temp \;

とすることで同様の結果を得ることができますが、xargs は find 以外のコマンドに対しても適用できます。

xargs の実践例

Dockerのコンテナを作成している場合、ビルド中にエラーを起こすとTAGが となることがあります。
ひとつならばいいのですが、それを一気に消したいと思いました。

これを以下で達成できました。

docker image ls | grep none | awk '{ print $3 }' | xargs docker image rm

簡単に解説します。

  • “docker image ls” は コンテナイメージを列挙します。

REPOSITORY TAG IMAGE ID CREATED SIZE
container1 latest 608d1c44a054 2 hours ago 55.4GB
container2 33f22ef999ce 2 hours ago 55.4GB
container3 latest 65c0b7b9a21f 21 hours ago 43.7GB
container4 e1bb0a89e972 5 days ago 53.7GB

  • “docker image ls | grep none” で、 none が入っているもののみ表示されます。

container2 33f22ef999ce 2 hours ago 55.4GB
container4 e1bb0a89e972 5 days ago 53.7GB

  • “docker image ls | grep none | awk ‘{ print $3 }'” で、 3列めの情報のみ表示されます。

33f22ef999ce
e1bb0a89e972

  • 最後に、これを ” |xargs docker image rm” に入れることで以下が実行されることになります。

docker image rm 33f22ef999ce e1bb0a89e972

ポイントは、xargs で受けるのは引数のリストとなるということでしょうか。

このように、パイプで受けること、引数の場所を意識することで、 xargs のポイントがわかった気がしました。

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください