このページでは、for文を使用したシェルスクリプトを作成します。 「シェルスクリプトの事例1」と異なり、 特にファイル名に規則性がない場合を想定しています。
作業用ファイルの作成1
「シェルスクリプトの事例1」では、 「temp1.txt」から1つずつ数字を増やして「temp100.txt」まで作りました。 今度は、(いくつでもいいのですが)3つずつ数字を増やしてファイルを作って みましょう。 「emacs」で「script2-1.sh」というファイルを作成します。下記の内容を 記述してください。
#!/bin/bash i=1 while [ "$i" -le 100 ] do touch temp${i}.txt i=`expr $i + 3` done
保存したら、chmodを使用して「script2-1.sh」を 実行形式に変更します。その後に、下記の赤字で表示されているように入力して 実行してみましょう。
bash-2.05$ ./script2-1.sh bash-2.05$ ls temp* temp1.txt temp22.txt temp4.txt temp55.txt temp70.txt temp88.txt temp10.txt temp25.txt temp40.txt temp58.txt temp73.txt temp91.txt temp100.txt temp28.txt temp43.txt temp61.txt temp76.txt temp94.txt temp13.txt temp31.txt temp46.txt temp64.txt temp79.txt temp97.txt temp16.txt temp34.txt temp49.txt temp67.txt temp82.txt temp19.txt temp37.txt temp52.txt temp7.txt temp85.txt
上記の結果でわかったように、「script2-1.sh」は 「script1-1.sh」は同様にtemp?.txt(またはtemp??.txt) という名前のファイルを生成するスクリプトです。 違いは、ファイル名の数字が3つおきになっている (temp1.txt、temp4.txt、…)というだけです。
作業用ファイルの作成2
今度は、(今度もいくつでもいいのですが)5つずつ数字を増やして ファイルを作ってみましょう。ただし、その前に注意することがあります。 既にファイルが存在しているか確認する必要があります。 そのためのスクリプトを「script2-2.sh」として作成します。下記の内容を 記述してください。
#!/bin/bash i=1 while [ "$i" -le 100 ] do echo "***** ${i} *****" if [ -e temp${i}.txt ] then echo "temp${i}.txt already exists !" fi i=`expr $i + 5` done
上記ではif文を使った条件分岐を行っています。 また、ファイルが存在するかどうかを「-e」という演算子 で判定しています。存在すれば真になります。
下記のように実行してみましょう。
bash-2.05$ ./script2-2.sh ***** 1 ***** temp1.txt already exists ! ***** 6 ***** ***** 11 ***** ***** 16 ***** temp16.txt already exists ! ***** 21 ***** ***** 26 ***** ***** 31 ***** temp31.txt already exists ! ***** 36 ***** ***** 41 ***** ***** 46 ***** temp46.txt already exists ! ***** 51 ***** ***** 56 ***** ***** 61 ***** temp61.txt already exists ! ***** 66 ***** ***** 71 ***** ***** 76 ***** temp76.txt already exists ! ***** 81 ***** ***** 86 ***** ***** 91 ***** temp91.txt already exists ! ***** 96 ***** bash-2.05$
上記の結果でわかったように、既にファイルが存在するときに「-e ファイル名」 が真となって、if文の中身が実行されます。
作業用ファイルの作成3
上記の「script2-2.sh」を踏まえて、 既にファイルが存在しているか確認しながら、5つずつ数字を増やして ファイルを作ってみましょう。 下記の内容を「script2-3.sh」として作成してください。
i=1 while [ "$i" -le 100 ] do echo "***** ${i} *****" if [ ! -e temp${i}.txt ] then touch temp${i}.txt fi i=`expr $i + 5` done
上記では、if [ ! -e temp${i}.txt ]となっていますが、 「!」で否定の意味ですから、 ファイルが存在しないときにif文の中身が実行される ということです。 実行すると下記のような結果がでるはずです。
bash-2.05$ ./script2-3.sh bash-2.05$ ls temp* temp1.txt temp22.txt temp4.txt temp55.txt temp7.txt temp85.txt temp10.txt temp25.txt temp40.txt temp56.txt temp70.txt temp86.txt temp100.txt temp26.txt temp41.txt temp58.txt temp71.txt temp88.txt temp11.txt temp28.txt temp43.txt temp6.txt temp73.txt temp91.txt temp13.txt temp31.txt temp46.txt temp61.txt temp76.txt temp94.txt temp16.txt temp34.txt temp49.txt temp64.txt temp79.txt temp96.txt temp19.txt temp36.txt temp51.txt temp66.txt temp81.txt temp97.txt temp21.txt temp37.txt temp52.txt temp67.txt temp82.txt
これで処理の準備が終わりました。次の内容からが本番です。
for文の基本構造は以下の通りです。
for 変数 in 変数名1 変数名2 ... do 実行文 done
for文の使用例:script2-4.sh
#!/bin/bash for file in temp1.txt temp4.txt temp6.txt do echo "*** ${file} ***" done
上記の「script2-4.sh」を実行させると、「file」という変数に、順次 「temp1.txt」「temp4.txt」「temp6.txt」という文字列が代入されていく ことがわかります。
script2-4.shの実行結果
bash-2.05$ ./script2-4.sh *** temp1.txt *** *** temp4.txt *** *** temp6.txt ***
ですが、このfor文においては予め「変数名1」「変数名2」を記述しなくては なりません。今回のように、「temp1.txt」から「temp100.txt」までの ファイルを対象とするように、変数名の数が多いときは非常に大変です。そこで、 「temp*.txtという名前のファイルだけを対象」とすると 仮定します。そうすると、下記のように非常にすっきりします。
for文の使用例:script2-5.sh
#!/bin/bash for file in `ls temp*.txt` do echo "*** ${file} ***" done
または下記の記述でも同じ結果となります。
#!/bin/bash for file in $(ls temp*.txt) do echo "*** ${file} ***" done
上記では、「ls temp*.txt」の実行結果が一つずつ 変数fileに代入されています。下記のように実行して確認してみてください。
script2-5.shの実行結果
bash-2.05$ ./script2-5.sh *** temp1.txt *** *** temp10.txt *** *** temp100.txt *** *** temp11.txt *** *** temp13.txt *** *** temp16.txt *** *** temp19.txt *** *** temp21.txt *** *** temp22.txt *** *** temp25.txt *** *** temp26.txt *** *** temp28.txt *** *** temp31.txt *** *** temp34.txt *** *** temp36.txt *** *** temp37.txt *** *** temp4.txt *** *** temp40.txt *** *** temp41.txt *** *** temp43.txt *** *** temp46.txt *** *** temp49.txt *** *** temp51.txt *** *** temp52.txt *** *** temp55.txt *** *** temp56.txt *** *** temp58.txt *** *** temp6.txt *** *** temp61.txt *** *** temp64.txt *** *** temp66.txt *** *** temp67.txt *** *** temp7.txt *** *** temp70.txt *** *** temp71.txt *** *** temp73.txt *** *** temp76.txt *** *** temp79.txt *** *** temp81.txt *** *** temp82.txt *** *** temp85.txt *** *** temp86.txt *** *** temp88.txt *** *** temp91.txt *** *** temp94.txt *** *** temp96.txt *** *** temp97.txt ***
それでは最後になりますが、 [3.シェルスクリプトの事例1]の 名前変更用スクリプト「script1-2.sh」のように、「temp001.txt」と 数字の桁を揃えたファイル名に変更するスクリプトを「script2-6.sh」として 作成してください。
「temp1.txt」の場合の「1」という数字を取り出すのに 「sed」を使用していま す。使い方が良くわからない場合にはリンク先を参照してください。
script2-6.shの例1
sed -e "s/temp//"で「temp」という文字列を取り除 き、さらに続けてsed -e "s/.txt//"で 「.txt」という文字列を取り除いていますから、結局数字だけが残り、変数iに 代入されます。
#!/bin/bash for file in `ls temp*.txt` do i=`echo $file | sed -e "s/temp//" | sed -e "s/.txt//"` if [ "$i" -lt 10 ] then num=00${i} elif [ "$i" -lt 100 ] then num=0${i} else num=${i} fi mv temp${i}.txt temp${num}.txt done
script2-6.shの例2
例1でもそうですが、やりたいのは 数字以外の文字およびドット(.)を取り除いて数字だけ残す という処理です。この例2では、 sed -e "s/[a-z.]//g"で 数字以外の文字およびドット(.)を全て取り除いていますから、 結局数字だけが残り、変数iに代入されます。
#!/bin/bash for file in `ls temp*.txt` do i=`echo $file | sed -e "s/[a-z.]//g"` if [ "$i" -lt 10 ] then num=00${i} elif [ "$i" -lt 100 ] then num=0${i} else num=${i} fi mv temp${i}.txt temp${num}.txt done
script2-6.shの実行結果
bash-2.05$ ./script2-6.sh bash-2.05$ ls temp* temp001.txt temp019.txt temp036.txt temp052.txt temp070.txt temp086.txt temp004.txt temp021.txt temp037.txt temp055.txt temp071.txt temp088.txt temp006.txt temp022.txt temp040.txt temp056.txt temp073.txt temp091.txt temp007.txt temp025.txt temp041.txt temp058.txt temp076.txt temp094.txt temp010.txt temp026.txt temp043.txt temp061.txt temp079.txt temp096.txt temp011.txt temp028.txt temp046.txt temp064.txt temp081.txt temp097.txt temp013.txt temp031.txt temp049.txt temp066.txt temp082.txt temp100.txt temp016.txt temp034.txt temp051.txt temp067.txt temp085.txt