bashの制御構文(for文、if文)
この記事の目的
シェルスクリプトで自分がいろいろ混乱しがちな制御構文の備忘録として記す。種類はbashシェルとする。
事前準備
[testuser@nuc-centos8 shelltest]$ touch test.sh [testuser@nuc-centos8 shelltest]$ chmod +x test.sh [testuser@nuc-centos8 shelltest]$ cat > test.sh #!/bin/sh echo hogehoge [testuser@nuc-centos8 shelltest]$ ./test.sh hogehoge
サンプルのファイルも置いておく。
[testuser@nuc-centos8 shelltest]$ ls fileA fileB fileC test.sh
制御構文
for文
for 変数 in 変数の取りうる値の列挙; do 処理 done
の形式になる。処理をdo~doneではさむこと、doの前にセミコロン;
が入ることがポイント。以下が実例。
#!/bin/sh for file in fileA fileB; do ls -i $file done
[testuser@nuc-centos8 shelltest]$ ./test.sh 144 fileA 145 fileB
列挙の部分は何らかのコマンドの実行結果にしてもよい。コマンドの実行結果を展開するので` `
で実行したいコマンドを囲う。
#!/bin/sh for file in `ls`; do ls -i $file done
[testuser@nuc-centos8 shelltest]$ ./test.sh 144 fileA 145 fileB 146 fileC 147 test.sh
シェルスクリプト内のセミコロンはシェル上のワンライナーで書く場合は、処理の後にもつける。
[testuser@nuc-centos8 shelltest]$ for file in `ls`; do ls -i $file; done 144 fileA 145 fileB 146 fileC 147 test.sh
if文
if [ 条件 ] then 処理 elif [ 条件 ] then 処理 else 処理 fi
の形式となる。if~fiで囲むこと、ifとelifの後はthenが入るが最後のelseの後は入らないこと、[ ]
(ブレース)の条件と左右の括弧の間は半角スペースが必要なことなどがポイントである。
#!/bin/sh if [ $1 -lt 3 ] then echo AAA elif [ $1 -eq 3 ] then echo BBB else echo CCC fi
[testuser@nuc-centos8 shelltest]$ ./test.sh 5 CCC [testuser@nuc-centos8 shelltest]$ ./test.sh 3 BBB [testuser@nuc-centos8 shelltest]$ ./test.sh 2 AAA
[ ]
とthen
を同一行に書くこともできるが、その場合は;
で区切る必要がある。ワンライナーで書いてみる。ワンライナーで書く場合は処理部分の最後にも;
が必要。
[testuser@nuc-centos8 shelltest]$ if [ `ls | wc -w` -eq 4 ]; then echo Yes; fi Yes
ファイルのタイプを確認できるtest
コマンドがあるが、if文の[ ]
の中身はtest
コマンドと同じである。
[testuser@nuc-centos8 shelltest]$ mkdir dir [testuser@nuc-centos8 shelltest]$ ln -s /etc/ [testuser@nuc-centos8 shelltest]$ ls -l total 4 drwxrwxr-x. 2 testuser testuser 6 Mar 19 01:23 dir lrwxrwxrwx. 1 testuser testuser 5 Mar 19 01:23 etc -> /etc/ -rw-rw-r--. 1 testuser testuser 0 Mar 19 00:31 fileA -rw-rw-r--. 1 testuser testuser 0 Mar 19 00:31 fileB -rw-rw-r--. 1 testuser testuser 0 Mar 19 00:31 fileC -rwxrwxr-x. 1 testuser testuser 93 Mar 19 01:07 test.sh
-f
で通常ファイルかどうかを確認する。$?
は直前のコマンドの終了ステータスで0は成功、1は失敗である。fileAは通常ファイルだが、dirはディレクトリなので以下のような結果になる。
[testuser@nuc-centos8 shelltest]$ test -f fileA; echo $? 0 [testuser@nuc-centos8 shelltest]$ test -f dir; echo $? 1 [testuser@nuc-centos8 shelltest]$ if [ -f fileA ]; then echo Yes; fi Yes [testuser@nuc-centos8 shelltest]$ if [ -f dir ]; then echo Yes; fi [testuser@nuc-centos8 shelltest]$
-d
で通常ファイルかどうかを確認する。dirはディレクトリだが、filrBは通常ファイルでディレクトリではないので以下のような結果になる。
[testuser@nuc-centos8 shelltest]$ test -d dir; echo $? 0 [testuser@nuc-centos8 shelltest]$ test -d fileB; echo $? 1 [testuser@nuc-centos8 shelltest]$ if [ -d dir ]; then echo Yes; fi Yes [testuser@nuc-centos8 shelltest]$ if [ -d fileB ]; then echo Yes; fi [testuser@nuc-centos8 shelltest]$
-L
でシンボリックリンクかどうかを確認する。etcはシンボリックリンクだがdirはそうではないので以下のようになる。
[testuser@nuc-centos8 shelltest]$ test -L etc; echo $? 0 [testuser@nuc-centos8 shelltest]$ test -L dir; echo $? 1 [testuser@nuc-centos8 shelltest]$ if [ -L etc ]; then echo Yes; fi Yes [testuser@nuc-centos8 shelltest]$ if [ -L dir ]; then echo Yes; fi [testuser@nuc-centos8 shelltest]$
参考にしたもの
【 expr 】コマンド――計算式や論理式を評価する:Linux基本コマンドTips(171) - @IT
www.atmarkit.co.jp testコマンド、条件分岐