【bash】ls、grepの「引数が長すぎます」をawkで回避
黒魔術っぽくて敬遠していたawkをちょっと触ってみると、やっぱり黒魔術だった
# 基本1 標準出力を空白文字区切りで分割し、後のスクリプトっぽい部分で一つ目なら$1、二つ目なら$2と書く。 ls foo | awk '{print $1 $2}' # 基本2 改行の分だけ動作を繰り返す # ls -1 ... ファイルの一覧を改行区切りで標準出力 ls -1 foo | awk '{print $1}' # 基本3 スクリプトっぽい部分"{ ... }"は bashではない。 # 独自(C言語っぽい?)文法。 ls -1 foo | awk '{ print "----- " $1 " -----"; # コマンドの字句を作成し、変数に保存 command = sprintf("cat foo/%s", $1); # bash実行。 buf = system(command); # ファイルディスクプリタを閉じる close(command); print ""; }' # 基本4 演算できる。なんだこの気持ち悪いインタプリタ echo 1 | awk '{ print $1 + 1 * 2 }' # 基本5 if もループもできる。 echo 1 | awk '{ for (i=1; i<100; i++) { sum += i; if (sum >= 100) { break; } } print "i:" i " sum:" sum; }'
スクリプト置くならえんやこら手続きがいるけど、手順書に乗っけるだけならば検証作業はいりませんなぁ(ゲス顔) その代わり、結構遅いんやねこれ。。
本題
grep "" dir/*/*/*/*
で、400byteのファイル×10万個ぐらいひっかけると、「引数が長すぎます」といわれて死んだ。
awkを使って、動的にコマンドを生成しつつ回避。
#/bin/bash # ファイルが 数万個のところでlsとかすると、「引数が長すぎます」とエラーが出る。 # awkを使って疑似回避。 # 非常に重たい。 ls -1d msgs/*/* | awk '{ command = sprintf("grep ERROR %s/*/*", $1); system(command); close(command); }'