それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

bash の for ループ : for in スタイル

bash の for ループは for ..in スタイル

bash では、for ループを for .. in スタイルで記述することが一般的です。 もちろん、C言語スタイルのbash のfor ループを記述することも可能です→参考

一般的に使われるのは for ... in スタイルではないでしょうか。言語によっては for each / foreach / イテレーション などとも呼ばれます。

for .. in スタイルの例

$ for name in takuya yuki koji ; 
do
   echo $name.txt ;
done
takuya.txt
yuki.txt
koji.txt

for in で記述する場合は、for の要素をスペース区切り直接文字列で記述することが出来ます。

コマンド結果と組み合わせる

for in ループは、そのまま単体で使うことは少ないです。コマンドの結果と組み合わせて使うほうがおなじみでしょう。 $( コマンド ) の結果を for in ループで回すことで柔軟な記述が可能になります。

$ for name in $( ls /Users/takuya ) ; do echo $name ; done
Applications
Desktop
Documents
Downloads
Library
Music
Pictures
Sites

ただ、for ループは記述が煩雑になるのと並列実効性能に乏しいので、実際には xargs を使うことが多いです。

空白 区切り文字を変更する

for ループは空白文字すべてで区切るため、コマンドの実行結果に空白文字が含まれると少々めんどくさい事になります

# 空白文字が含まれる例
#次のようなディレクトリがあるとき
takuya@Desktop$ ls   /Applications/ | /usr/bin/grep -i Google
Google Chrome.app
Google Drive.app
Google Photos Backup.app
Google SketchUp 8
GoogleJapaneseInput.localized
## めんどうなことに・・・
takuya@Desktop$ for i in $( ls   /Applications/ | /usr/bin/grep -i Google ) ; do echo $i ;done
Google
Chrome.app
Google
Drive.app
Google
Photos
Backup.app
Google
SketchUp
8
GoogleJapaneseInput.localized

区切文字は環境変数IFSで決める

環境変数 IFS を指定すると、区切り文字を任意の文字列にすることが出来ます。

IFS 指定の例
takuya@Desktop$ IFS=$'\n'
takuya@Desktop$ for i in $( ls   /Applications/ | /usr/bin/grep -i Google ) ; do echo $i ;done
Google Chrome.app
Google Drive.app
Google Photos Backup.app
Google SketchUp 8
GoogleJapaneseInput.localized

空白を含む結果も無事に1行ごとに処理することが出来ます。

IFS=$'\n'について

IFSの指定で、改行を指定するのは次のように行います。

IFS='
'

ただし、これではあまりにわかりにくいです。また、bash履歴・ヒストリにもうまく残りません。 そこで、$ を使ってエスケープシーケンスを解釈させています。

IFS=$'\n'

for in と ブレース展開の組み合わせ。

for in ループは、bash のブレース展開と組み合わせて使うと便利に使うことが出来ます。

# for ..in ブレース展開の例
for idx in {00...5};  do echo $idx.jpg ; done

此のコマンドは次のような結果を得ます。

000.jpg
001.jpg
002.jpg
003.jpg
004.jpg
005.jpg

for と組み合わせてさらにコマンドを実行するときに便利です。 単に文字列を作成するだけなら、 ブレース展開だけで済んでしまう場面が多いことでしょう。

xargs の活用

しかし、わたしは、for ループより、じっさいには xargs を使うことが多いです。

for で記述するよりも xargs のほうがあとで再利用可能な履歴が残りやすく、再利用性を考慮するとxargs の方がいいことが多いです。

xargs には、並列実行のパラレル機能があり、コマンドの終了を待たずに次の処理を開始できることがあるためです。→ 並列実行はxargsコマンドのマルチプロセスを使うと楽ちん高速化ですね。 - それマグで!

参考資料

新しいLinuxの教科書