xargs の使い方メモ

たまにしか使わないで済んでいるのでいつも使い方を忘れる。

基本

コマンドの出力をパイプで渡すと、各行をコマンドの最後の引数として実行する。

ls | xargs md5 -q

これは次のように展開されたものと同じ。

md5 -q foo
md5 -q bar
md5 -q baz
...

ただしファイル名にスペースを含んでいると上記の方法ではうまくいかない。この場合、次の節で説明するプレースホルダを使用する。

プレースホルダ

xargs では -I オプションで引数を展開する場所を指定することができる。-I '{}' のように指定すると、{} の場所に引数が展開される。

ls | xargs -I '{}' md5 -q '{}'

これでスペースを含むファイル名もうまく展開される。

md5 -q 'foo'
md5 -q 'bar'
md5 -q 'foo bar'
...

処理系によっては小文字の -i オプションで -I '{}' と同等の動作になるので alias を指定しておくと便利かもしれない。

alias xargs-i='xargs -I "{}"'

拡張子の変更

xargs を使って拡張子を一括置換するにはプレースホルダに加え、 sed を組み合わせるとよい。

find . -name '*.txt' | sed -e 's/[.]txt$//' | xargs -I '{}' mv '{}.txt' '{}.md'

応用例として、 FFmpeg で動画から音声トラックのみ抽出するコマンドを挙げる。

find . -name '*.mp4' | sed -e 's/[.]mp4$//' | xargs -I '{}' ffmpeg -i '{}.mp4' -c:a copy '{}.m4a'

Windowsスクリーンショットを一括で JPEG に変換してリネーム

PowerShell は使わず、WSL の bashzsh などから使用する。ImageMagick (convert コマンド) がインストールされているものとする。

ls スクリ*.png | \
    sed -e 's/スクリーンショット (//' -e 's/)[.]png//' | \
    xargs -I '{}' convert 'スクリーンショット ({}).png' 'image-{}.jpg'

一部を切り抜きたい場合はその座標を指定して

# -crop (width)x(height)+(left)+(top)
ls スクリ*.png | \
    sed -e 's/スクリーンショット (//' -e 's/)[.]png//' | \
    xargs -I '{}' convert 'スクリーンショット ({}).png' -crop 1140x641+601+199 'image-{}.jpg'