シェルスクリプト中でファイルサイズをポータブルに得る方法
ファイルサイズを得たい!ってときに真っ先に思い浮かぶのは stat(1) にサイズを表示させるフォーマットを指定する方法。
だけど GNU stat -c %s $FILENAME に対して、BSD stat -f %z $FILENAME と、オプションもフォーマットも違う。
次に思いつくのは ls -l の結果を利用すること。
% ls -l $FILENAME | while read a b c d e f do echo $e done
これは GNU ls でも BSD ls でもちゃんとファイルサイズを表示する。
しかし、ファイルサイズを得たいのに ls -l を使うのはちょっと大げさな気もする。
もう少しマシな方法は wc -c を利用すること。GNU wc と BSD wc で微妙に表示の仕方が違う*1けど、問題無い。
% wc -c $FILENAME | while read a b do echo $a done
こっちのほうが ls -l より早い。1000回まわして1秒くらいの差が出る。
というか、read a b; echo $a とは書けないのかなぁ。ksh, zsh ならこれでいけるんだけど、bash だとダメ。
csh は知らね。
当然 awk '{print $1}' にしてもいいんだけど、そうするとまた処理が遅くなる。
Command-line fu でもやたらと awk '{print $N}' が登場するけど、それくらいならビルトインの read を使ったほうがいいと思うんだけどなー。
while IFS=, read a b c; とかよくやってる。
awk を使うなら、パターンマッチを含む処理*2とか、BEGIN{} と END{} を使うようなものでないと。
まぁ bash で while を使うとサブシェルの罠が待っていたりするわけだけど。
おまけ。
zsh に限定すれば、さらに良い方法がある。
% zmodload zsh/stat % stat +size $FILENAME
stat をビルトインで持っている。ビルトインだから当然圧倒的に早い。zsh 最強すぐる!
こんなところか。