いまさら findと xargsと parallelの便利さを主張してみる
hnwさん、細かいツッコミをいれます。生産性が上がるわけでもないので、あまりしらなくていいことですが。
コマンドを一度に起動する (find -exec +)
$ find . -name \*~ -exec rm {} \;ただ、これだと100000ファイルがヒットした場合にrmコマンドが100000回実行されてしまうため、全部実行するまでに案外時間がかかる、なんてことがあります。
http://openlab.dino.co.jp/2008/02/20/133431188.html
これを回避するために xargsを使うのもまっとうですが、最近の find には + というのがあります (SUSV3 で定義されていて、 MacOS Xでも GNUでも (多分) BSDでも使えます)。
find . -name \*~ -exec rm {} +
これで、複数の引数つけて rmを呼んでくれます。空白があっても okです。
真ん中に展開したい (xargs -J)
でも mvのように真ん中に展開したい引数がある時はだめ。'{} +' で終わってなきゃいけないってルールなんですね。せこい。
% find . -name \*~ -exec mv {} bak/ + find: -exec: no terminating ";"
この場合は GNU coreutilsを使わなきゃいけないかというと、それも抜け道があります。
BSD系 xargsには -J optionがあります:
% touch a~ b~ c~ % find . -name \*~ -print0 | xargs -0 -J {} echo mv {} /var/tmp mv ./a~ ./b~ ./c~ /var/tmp
というように一つのコマンドに展開してくれます。これで GNUよりも BSDが好きな自分のようなやつでも、coreutilsを入れずに幸せになれます *1。
このほうが cp とか mv とか、個々の commandに optionつけるよりエレガントじゃん、と思います。
ちなみに BSD系では template変数が2文字以上の時、"-J{}" とくっつけるとだめで "-J {}" と spaceをいれないといけないよう。普段は "-J@" って、一文字にしてるので気づかなかった。
追記: GNUの xargsでも -n をつければ複数展開してくれますね:
% find . -name \*~ -print0 | xargs -0 -I {} -n 100 mv {} /var/tmp
てな感じで。100 ってのが adhocな感じだけど。
MacOSではこの方法は使えませんでした。環境によって方法を選ばないといけないってのは面倒だな。間違いでした。GNUの xargsはそういう動作ないみたいですね..
もっと早くしたい (けど) (parallel)
でも昨今は multicoreや hyperthreadな CPUが主流でしょう。そんなときに一つの threadで順番にやるのはアホです。そういうときに使えるのがparallel です。最大 10個分プロセスを立ち上げて、文字通り並列に CPUを余すことなく使ってくれます。
% ls | ./parallel 'sleep 3 ; echo ' & (sleep 1; ps ) [1] 4503 4504 PID TT STAT TIME COMMAND 769 p2 Ss 0:00.22 -bin/tcsh -i 4504 p2 S 0:00.08 /usr/bin/perl -w ./parallel sleep 3 ; echo 4507 p2 S 0:00.01 sh -c sleep 3 ; echo Makefile 4508 p2 S 0:00.00 sh -c sleep 3 ; echo gpl-3.0.txt 4509 p2 S 0:00.00 sleep 3 4510 p2 S 0:00.00 sleep 3 4511 p2 S 0:00.01 sh -c sleep 3 ; echo parallel 4512 p2 S 0:00.00 sh -c sleep 3 ; echo parallel.1 4513 p2 S 0:00.00 sleep 3 4514 p2 S 0:00.00 sleep 3 4515 p2 S 0:00.01 sh -c sleep 3 ; echo unittest 4516 p2 S 0:00.00 sleep 3
いや、実のところ一つ一つの引数に対して processを立ち上げるので、全体としてはおそいっす。今まであげてきた rm や mvなどでは恩恵を受けられないでしょう。
マニュアルの例では wgetや convertなど、一つ一つそれなりに時間がかかるもっともな例をあげてます。さもありなん。
まあ、でも multicore時代には、こういう富豪的に CPUを使うような環境が普通になっていくんでしょう。そもそも CUIなんて富豪的じゃないってツッコミは置いといて。