xargs コマンドを使用した複数プロセスによる並列処理
大量のファイルを HTTP でダウンロードするときや、複数のタスクを並列に実行したいとき、プログラム自体を並列に書き直すのは手間がかかります。そこで、便利なのがシェルの xargs
コマンドです。
GNU 版 xargs
を使えば並列処理をお手軽に実現できます。
xargs
コマンドについて
xargs
コマンドは、標準入力から別のコマンドにコマンドライン引数を与えるコマンドです。
例えば、xargs ls
と打った後に標準入力から -A
を入力すると(入力完了後に Return キーを押してから Ctrl + D を押します)、ls -A
を実行することと同じになります1。もし標準入力から複数行の入力をする場合、新たな行も引数の区切りとみなされます。
-L
オプション
xargs
の -L
オプションは一度に与える引数の数を制限します。このオプションをつけないと、シェルが許す最大値までコマンドライン引数を一度に与えてしまいます。
例えば、seq 1 10 | xargs echo
は、echo 1 2 3 4 5 6 7 8 9 10
と同じになります。
しかし、単一の引数しかとらないようなプログラムではこの挙動は問題となります。そこで -L
オプションを使い一度に与える引数の数を制限します。例えば、seq 1 10 | xargs -L 3 echo
は echo 1 2 3; echo 4 5 6; echo 7 8 9; echo 10
と等価です。つまり、引数の数が指定数を超えた場合は、別々のプロセスを開始し逐次実行して処理します(並列実行ではない)。
-P
オプション
-L
オプションと組み合わせて、並列実行を行うことができる -P
オプションが存在します。このオプションを使うと、一度に複数のプロセスを立ち上げて処理を実行することが可能になります。デフォルトは 1 で直列の逐次処理になりますが、-P 8
と付け加えると xargs
は最大で 8 個のプロセスを起動して、適切にタスクを回してくれます。
使用例
仮に、連番の Zip ファイルがサーバーに置かれていて、番号を与えると対応する Zip をダウンロードする Python スクリプトを作成したとします。その場合、1〜100 の Zip を最大 8 プロセス並列でダウンロードするコマンドは以下のようになります。
seq 1 100 | xargs -P 8 -L 1 python3 download.py
補足
PowerShell 7.0 以降は ForEach-Object -Parallel
で同様のことができます。
コマンドラインの中間に引数を挿入する場合は
-I
オプションを使います。 ↩︎