for文 ループ処理
変数に指定の値を代入しながらループ処理します。
まずは一番簡単で基本的な考え方が分かる構文です。
「in」直後の「代入値」を「変数名」に変数として設定(1回目は「変数名=代入値1」。2回目は「変数名=代入値2」)して「do」と「done」に囲まれた「処理」を実行。この「処理」部分をループして行います。シェル変数の値は最後に代入した値がfor文を抜けてもそのまま残る事に気を付けてください。
for 変数名 in 代入値1 代入値2 代入値3 ・・・・; do
処 理
・
・
done
例として、/home/fedora/tmp 配下にある、拡張子が「txt」「sh」「xls*」のファイルを/backupディレクトリ配下にコピーする。
をfor文にすると・・・
for FILE_EXT in *.txt *.sh *.xls*; do
cp -p /home/fedora/tmp/$FILE_EXT /backup/
done
ここまでがチョ~基本的なfor文構成です。
そして代入値の設定の仕方でfor文を応用していく事ができます。
「in 代入値」の省略
「in 代入値 ・・・」を省略する事ができます。
その場合は「in "$@"」と同義になります。(引数で与えた値を代入してループしていくという事。)
基本構文と考え方は変わらず、シェル内で指定していた代入値をシェル実行時の引数として渡した数分ループ処理を行います。
for FILE in "$@"; do
cp -pr $FILE /backup/
done
「in $@」を省略すると書き方は以下になります。
for FILE; do
cp -pr $FILE /backup/
done
パス名展開を使う
代入値の代わりに「*」を使う事でカレントディレクトリにある全てのファイルやディレクトリ(基本は「.」から始まる隠しファイルやディレクトリはコピー対象外になります。)を代入値として設定する事ができます。
また、「*」ではなく「*.txt」とか「image[0-9]*.jpg」というような指定もできます。
for FILE in *; do
cp -pr $FILE /backup/
done
上記の例ではカレントディレクトリのファイルとディレクトリを/backup 配下にコピーします。
ここでcpコマンドのオプションに「r」を入れないとファイルのみコピーします。
コマンド置換でリストファイルを使った繰り返し
1行に1ファイルずつ記載したリストファイル(list.lst)を用意しておけば、コマンド置換(バッククォート)でリストファイルを読み込み、記載したファイルに対してfor文を実行する事ができます。
*.txt
*.sh
*.xls*
cd /home/fedora
for FILE_EXT in `cat list.lst`; do
cp -p $FILE_EXT /backup/
done
コマンド置換でリストファイルを読み込む方式ではリストファイル内にあるファイル名などにスペースやタブ、改行や*、?などのパス名展開の文字が含まれていると正常に動作しません。かといってダブルクォートを使って「"`cat list.lst`"」としても正常に動作しません。(どういうことか確認中)
終了ステータス
最後のループの処理内の最後のコマンドの終了ステータスがfor文としての終了ステータスになります。
ただし、
ループが1回も実行されたかった場合(in の直後に空のシェル変数をダブルクォート(" ")無しで指定した場合)は終了ステータスが0となります。
continue
「continue」を記載するとその回のループを終了し、次の回のループへ移行します。
例えば、先ほどのリストファイル(list.lst)にコメント行があるとして、シェル側のfor文にコメント行はcontinueコマンドを使ってその回のループを終了させる。という処理を追加すると・・・
# バックアップ対象ファイルを記載します。
*.txt
*.sh
*.xls*
for FILE_EXT in `cat test.lst`; do
# コメント行で始まる行は無視(continue)する。
if [[ $FILE_EXT =~ ^#.* ]] ; then
continue
fi
cp -p $FILE_EXT /backup_dir/
done
break
breakを実行するとその時点でfor文を抜けます。
一定回数ループ
ループ回数が決まっている時には原始的な方法に見えるが、インクリメントをしたりする必要が無いので簡単です。
for i in 0 1 2 3 4 5 6 7 8 9; do
echo $i
done