シェルスクリプト入門【書き方のまとめ】

Linuxでシェルスクリプトを書くために必要な基礎知識をまとめました。「作成方法・実行方法」「変数」「if、forなどの制御構造」「条件文の作り方」など解説します。

シェルスクリプトの作り方・実行方法

スクリプトを作成して直接実行

まずは簡単な例です。「hello」というスクリプトを作成して実行させます。

#!/bin/bash
 
echo "Hello World"
$ vi hello
$
$ ls -l hello
-rw-r--r--  1 wakuwaku  staff  33 Nov 18 12:12 hello
$
$ chmod u+x hello
$
$ ls -l hello
-rwxr--r--  1 wakuwaku  staff  33 Nov 18 12:12 hello
$
$ ./hello
Hello World

ここで、押さえておきたいポイントは2つです。

  • スクリプトの1行目に「bashで実行されます」という宣言を記述。
  • ファイルの所有者のパーミッションに実行権を付与。
    • u(所有者) g(グループ) o(その他)
    • x(実行権)

PATHを通して実行

環境変数PATHに、「hello」が置かれているディレクトリパスを追加すると、ファイル名を指定するだけで実行できます。

PATHが通ってない状態ですと、command not foundとなります。

$ hello
bash: hello: command not found

PATHの設定は以下コマンドで確認できます。

$ echo $PATH

PATHの追加は、下記のように行います。

$ export PATH=$PATH:追加したいパス

実際に確認します。

$ ls
hello
$
$ pwd
/tmp
$
$ export PATH=$PATH:/tmp
$
$ hello
Hello World

bashコマンドで実行

bashコマンドから起動することもできます。

「-v」オプションを利用すると全行エコー表示されます。

$ bash -v hello
#!/bin/bash

echo "Hello World"
Hello World

「-x」オプションを利用すると実行文がエコー表示されます。

$ bash -x hello
+ echo 'Hello World'
Hello World

「ファイルを直接実行」「bashコマンドで実行」とした場合、新しくシェルが起動されて実行されます。つまり、現在のシェルに影響を与えません。

sourceコマンド、
ドット(.)コマンドによる実行

sourceコマンド ドット(.)コマンド で実行した場合、実行したシェル(カレントシェル)から起動されます。つまり、現在のシェルに影響を与えます。 例えば、スクリプト内でcdを行なっていれば、スクリプト実行後、ディレクトリが移動された状態になります。

変数

シェル変数

ローカル変数のようなもので、子プロセスでは引き継がれません。

全ての変数の設定を表示

set

指定した変数の設定を表示

set | grep 変数名

変数に値を設定

変数名=値

余計なスペースを入れないでください。

変数の定義を削除

unset 変数名

環境変数

グローバル変数のようなもので、子プロセスでも引き継ぎます。

シェル変数を環境変数に変更

export  シェル変数名

環境変数の変更

export <オプション> 環境変数名=値

実行するコマンドにのみ環境変数を一時的に設定

env 環境変数名=値 コマンド

変数の出力

#!/bin/bash
string="Hello world"
 
echo $string
echo '$string'
echo "$string"
echo ${string}
Hello world
$string
Hello world
Hello world

'(シングルクォート) で囲むと展開されません。

変数を数字として扱う方法

シェル変数は文字です。なので、下記のように文字として表示されます。

$ cat add1
#!/bin/bash

x=3
y=10
z=$x+$y
echo $z
$
$ ./add1
3+10

数字として扱うには、下記のように$(( ))で囲みます。

$ cat add2
#!/bin/bash

x=3
y=10
z=$((x + y))
echo $z
$
$ ./add2
13

コマンド置換(コマンドの出力結果を文字列として利用する方法)

$() で囲む、もしくは バッククォート で囲みます。個人的には、$() の方が見やすいです。

$ echo "今日は$(date)です"
今日はSun Nov 18 12:51:28 JST 2018です
$
$ echo "今日は`date`です"
今日はSun Nov 18 12:51:47 JST 2018です

引数

特殊変数で引数を取得できます。

特殊変数 概要
$0 シェルスクリプトのファイル名
$1 1 番目の引数
$2 2 番目の引数
$# 引数の数
$$ プロセス番号
$* 全引数リスト("$1 $2 … $n")
$@ 全引数リスト("$1" “2" … "n”)

下記スクリプトで動作確認します。

#!/bin/bash

echo $0
echo $1
echo $2
echo $#
echo $$
echo $*
echo $@
$ ./arg aaa bbb ccc ddd
./arg
aaa
bbb
4
92494
aaa bbb ccc ddd
aaa bbb ccc ddd

制御構造

if文

if 条件式
 then
  実行文1
 else
  実行文2
fi
$ cat if 
#!/bin/bash

if [ 1 -ge 2 ]
 then
  echo "AAA"
 else
  echo "BBB"
fi
$ 
$ ./if 
BBB

case文

case 条件式 in
     値1)
          実行文1;;
     値2)
          実行文2;;
      :
      :
esac
$ cat case 
#!/bin/bash

x=BBB
case $x in
     AAA)
          echo "AAA"
          ;;
     BBB)
          echo "BBB"
          ;;
     CCC)
          echo "CCC"
          ;;
     *)
          ;;
esac
$ 
$ ./case 
BBB

for文

for  変数名  in  変数に代入する値のリスト
do
     実行文
done
$ cat for 
#!/bin/bash

for  i  in  `seq  10  15`
do
     echo  $i
done
$ 
$ ./for 
10
11
12
13
14
15

while文

while  条件文
do
     実行文
done

以下例では、現在の分数が10分以上のときだけ hello と出力します。

$ cat while 
#!/bin/bash

while true
do
    MINUTE=`date +"%M"`
    if test ${MINUTE} -ge 10
        then
              echo ${MINUTE}
              echo "hello"
              sleep 60
        else
              echo ${MINUTE}
              sleep 60
    fi
done
$ 
$ ./while 
15
hello
16
hello

条件文の作り方

条件文の書式

testコマンドを利用する方法

if test 1 -ge 2
 then
  echo "AAA"
 else
  echo "BBB"
fi

[] で囲む方法

if [ 1 -ge 2 ]
 then
  echo "AAA"
 else
  echo "BBB"
fi

条件式と[]の間にスペースが必要なので注意してください。

応用例

特定のファイルに特定の文字列が含まれていない場合、echoする

grep xxx file_path > /dev/null
if test $? -ne 0
 then
  echo "AAA"
fi

$? には、最後に実行したコマンドの exit値(終了ステータス) が入力されています。
一般的に以下の値が入力されます。

  • コマンド成功時には 0
  • 失敗時には 1

ファイル判定

書式 判定内容
-d ファイル名 指定したファイルが ディレクトリ なら真
-f ファイル名 指定したファイルが 通常ファイル なら真
-L ファイル名 指定したファイルが シンボリックリンク なら真
-r ファイル名 指定したファイルが 読み取り可能 なら真
-w ファイル名 指定したファイルが 書き込み可能 なら真
-x ファイル名 指定したファイルが 実行可能 なら真
-e ファイル名 指定したファイルが 存在すれば
-s ファイル名 指定したファイルの ファイルサイズが0より大きければ

文字列判定

書式 判定内容
-n 文字列 文字列の長さが0より大きければ真
-z 文字列 文字列の長さが0であれば真
文字列1 = 文字列2 2つの文字列が等しければ真
文字列1 != 文字列2 2つの文字列が等しくなければ真

数値判定

書式 判定内容
数値1 -eq 数値2 2つの数値が等しければ真
数値1 -ge 数値2 数値1が数値2以上であれば真
数値1 -gt 数値2 数値1が数値2より大きいのであれば真
数値1 -le 数値2 数値1が数値2以下であれば真
数値1 -lt 数値2 数値1が数値2未満であれば真
数値1 -ne 数値2 2つの数値が等しくなければ真

論理結合

書式 判定内容
!条件 条件が偽であれば真
条件1 -a 条件2 AND条件
条件1 -o 条件2 OR条件

その他豆知識

関数

$ cat function 
#!/bin/bash

HelloWorld()
{
        echo "Hello World"
        echo "Hello World"
}
 
HelloWorld
$ 
$ ./function 
Hello World
Hello World

引数は、通常のシェルスクリプトと同様に $1 $2 などの形でアクセスできます。

※豆知識

  • unset 関数名
    • 関数を削除します。
  • declare -f
    • 定義されている関数のみを表示します。
    • setでは変数と関数の両方が表示されます。

コメント

一行コメント

# echo "Hello world!"

複数行コメント

<<COMMENT
echo "Hello world!"
echo "Hello world!"
echo "Hello world!"
COMMENT

COMMENT の箇所は任意の文字列でかまいません。

キーボード入力受け付け

標準入力からの入力を受け付けるには、readコマンド を利用します。
下記例では、キーボードから入力した文字列を、変数usernameに格納しています。

read  username
echo  "Hello, $username!"

内部コマンドの確認

testread は内部コマンドです。

内部コマンドの一覧を表示するには、helpコマンドを利用します。
内部コマンドの説明を確認するには下記のようにします。

help  内部コマンド名