c/fe

http://d.hatena.ne.jp/uzulla から移行しました。

argument list toooooooooooooooooooooooooooooooooooo long

仕事で超大量のファイルをコピーする事が多いのだが、何も考えずに作業すると

[root@sv file]# cp -R * /path/to/
bash: /bin/cp: Argument list too long

となるのがありがち。
同様に、rmとかでもなる。
rm 20080101*
rm 20080102*

などと順番にやるのはいかにもダサい。


理屈を書くと、これはシェルで*が展開されて

cp -R dir1 dir2 dir3 ... dir9999 /path/to

というコマンドを処理しようとしたが、引数が長すぎるよアホ、と言われている。
引数の限度は案外短いのだ。

  • -

こういうときにはxargsを使う。

ls * |xargs rm

とかすると、
rm dir dir dir dir dir dir dir dir dir ... dir dir dir
と「怒られない範囲で、できるだけ長くした状態で」実行してくれるという便利なコマンドである。

xargsは標準入力からファイル名(Path)を受け取り、引数に数珠つなぎする。
勿論ファイルリストや、findから渡してもちゃんと動く。

  • -

ただ、上のrmではわかりやすいが、コレをcpでやろうとすると

ls * |xargs cp /path/to

などとやったら
cp /path/to dir dir dir ... ndir
となってしまって、うまくうごかない、というかndir に全部つっこまれてしまい、悲惨な結果となる。


勿論xargsだってバカじゃないので、

ls * | xargs -i cp {} /path/to

と、-iオプション付きで実行すれば、差し込む場所を指定できる。

  • -

ただ、これしばしば忘れるんだよなー、ということで

ls * |xargs cp --target-directory=/path/to

というバージョンを覚えておく事をお勧めしたい。*1


そんだけの話。

*1:これで、前方の引数でコピー先が指定できる