シェルスクリプト上のループ処理について
Bourne Shell系列での話です。
for
概要
リストの値を順番に処理する。
私の場合は、処理する対象が事前に決まっている場合はforを使う傾向が多いです。
構文
for 変数 in 変数に渡す値のリスト
do
処理
done
例
順番に表示
$ for VAL in 1 2 3
> do
> echo $VAL
> done
1
2
3
カレントディレクトリのテキストファイルをEUCに変換する
$ for FILE in `ls *.txt`
> do
> nkf -e ${FILE} > ${FILE}.euc
> done
カウントダウン
Linuxで確認しています。BSDはjot
を使ってください。
$ for CNT in `seq 10 -1 1`
> do
> echo $CNT
> sleep 1
> done
10
9
8
7
6
5
4
3
2
1
while
概要
ある条件の間ループする。
ファイルから値を読み込むときに使うことが多いです。他には、ファイルが作成されたかを監視するときに無限ループさせるのに使ったりします。
構文
while 条件
do
処理
done
例
ファイル読み込み
while read COL1 COL2 COL3
do
COL=`expr $COL1 + $COL2 * $COL3`
echo $COL
done < data.tsv
この例だとTSVファイルですが、IFS
を変更することで、CSVファイルを読み込むことができます。
OLD_IFS=$IFS
IFS=","
while read COL1 COL2 COL3
do
COL=`expr $COL1 + $COL2 * $COL3`
echo $COL
done < data.csv
IFS=$OLD_IFS
使ったら元に戻しておきます。
無限ループ
CSVファイルを出力するあるバッチ処理の処理状況を確認したいとき、よくこんな感じで監視します。
Ctrl-Cで止めます。
while true
do
date
ls -ltr result_*.csv
sleep 10
done
find
概要
あるディレクトリ配下のファイル/ディレクトリのうち、条件にマッチしたものを抽出するのがfind
です。
grep
する
例えばカレントディレクトリ配下にある*.c
ファイルを対象にgrep
するとき
find ./ -type f -name '*.c' -exec grep -n GREP_WORD /dev/null {} \;
とやったりします。
でも、カレントディレクトリ配下のディレクトリ名、ファイル名にスペースがないことが分かっているなら、こっちの方が速いです。
find ./ -type f -name '*.c' | xargs grep -n GREP_WORD
CYGWINを使っている場合、Program Files配下のファイルを取得しようとするとディレクトリ名にスペースが入っているため、xargs
にうまく情報を渡すことができない場合があります。そういうときはfind
のexec
アクションを使いましょう。
for
の対象を抽出する
あるディレクトリ配下のファイルを抽出し、for
で処理したいときにfind
を使ったりします。
for FILE in `find ./ -type f -name '*.c*'`
do
nkf -e ${FILE} > ${FILE}.euc
done