シェルスクリプトの事例2

このページでは、for文を使用したシェルスクリプトを作成します。 「シェルスクリプトの事例1」と異なり、 特にファイル名に規則性がない場合を想定しています。

1. 作業用ファイルの作成

  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. 作業用ファイルの作成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. 作業用ファイルの作成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
    

これで処理の準備が終わりました。次の内容からが本番です。

2. for文によるファイルへの処理

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

[1.シェルスクリプトの基本] [2.シェルスクリプトの制御文] [3.シェルスクリプトの事例1]
[UNIXコマンドのページへ戻る] [須崎純一のページへ戻る]
須崎純一 京都大学大学 工学研究科都市環境工学専攻 環境情報学講座