So-net無料ブログ作成
検索選択

Unix系コマンドのワイルドカード(*)にご注意?! find/xargsを使おう [Solaris]

久しぶりにSolarisのコマンドでハマリましたので、Tipsで残しておきます。

ログファイルを格納しているディレクトリに対して、ls -l *.logって実行すると「Argument list too long.」 や「引数が多すぎます 」、「引数リストが長すぎます」などとエラーになります。

これは、ワイルドカード(*)がシェルの内部処理によって展開され、コマンドラインのサイズをオーバーしてしまうかです。例えば、a.logとb.logの2つのファイルが存在し、ls -l *.logとすると、ファイル名展開により、ls -l a.log b.logになります。シェルが展開した文字数は、OS毎に制限があり、solarisでは1MB(1,048,320)、Linux(Ubuntu10.10)では2MB(2,097,152)になっています。

使っているOSのARG_MAXを参照すれば、コマンドラインサイズがわかります。
% getconf ARG_MAX

では、コマンドラインサイズを超えてしまうls -l *.logをどのようにすれば、できるのでしょうか。
①findを使う
find . -name \*.log -exec ls -l {} \;
(-execでは1ファイル毎にls -lが行われるため、非常に遅い)

②find+xargsを使う
find . -name \*.log | xargs ls -l

③grepを使う
ls -l | grep .log

lsで表示できたものを削除したい場合には、rm *.logとしたいところですが、これもエラーになります。こんなときは、xargsを使うと効率的にrmができます。

①xargsを使ってrmする
ls | grep .log | xargs rm
または
find . -name \*.log | xargs rm

②findを使ってrmする
find . -name \*.log -exec rm {} \;
(1ファイル毎にrmが行われるため、非常に遅い)

同様にtarでまとめたい時もxargsを使うと効率的に可能です。
①xargsを使ってtarする
ls | grep .log | xargs tar rvf /tmp/logs.tar
または
find . -name \*.log |xargs tar rvf /tmp/logs.tar

②findを使ってtarする
find . -name \*.log -exec tar rvf /tmp/logs.tar {} \;
(1ファイル毎にrmが行われるため、非常に遅い)

最近では、コマンドラインサイズも大きくなってきているので、エラーになる確率も減っていると思います。
xargsをうまく使うことで、処理時間の短縮が図れますので、是非xargsをご利用ください。