シェルスクリプトの基本
# コメント
# 下記のように改行すると複数のコマンドを順番に実行できる
ls
cat test.txt
# ; を使うと複数のコマンドを一行仁鶴ことができる
ls;cat test.txt
# 改行は「\」を使用する(パイプライン「|」を使用する場合は、「|」の直後に改行をいれてもいい)
cat \
test.txt
# 変数(参照するには$を使用)
# 変数名は英語、数字、「_」のみ使用可能
var='1'
echo $var
# コマンドか変数か不明になる場合は変数展開を使用する
file_name='test'
cat {$file_name}.txt
# コマンド置換
# 現在の日付のファイルを作成
file_name=$(data '+%Y-%m-%d')
touch "$file_name"
# 位置パラメーター
# シェルスクリプトの引数に「*」を使用した場合はカレントディレクトリのファイルが挿入される
# シェルスクリプトの引数をシェルスクリプト内で取得するには、$0、$1、$2...を使用する
# 引数の個数は$#で取得できる
# 引数全体を取得する場合は、$@あるいは、$*を使用する
# ifの使い方
if [ "$1" = "test" ]; then
echo "TRUE"
elif [ "$2" != "test" ]; then
# 文字列の評価
# = : 等しい
# != : 等しくない
# -n str : strは空文字ではない
# -z str : strは空文字である
elif [ "$3" -lt 0 ]; then
# 数値の評価(整数にしか使えない)
# -eq : 等しい
# -ne : 等しくない
# -lt : <
# -le : <=
# -gt : >
# -ge : >=
elif [ -e ./test.txt ]; then
# ファイル属性の評価
# -e file : fileは存在しない
# -d file : fileはディレクトリとして存在する
# -f file : fileはファイルとして存在する
# -r file : fileは書き込み権限がある
# file1 -nt file2 : file1はfile2より更新時刻が新しい
elif [ "$4" = 'test' -a "$5" = 'test' ]; then
# AND演算子
elif [ "$4" = 'test' -o "$5" = 'test' ]; then
# OR演算子
elif [ \( "$4" != 'test' -o "$5" != 'test' \) -a "$6" != 'test' ]; then
# 条件の結合には()を使用する(ただし、エスケープが必要)
else
echo "FALSE"
fi
# 条件式の省略
# test.txtがあれば、testと出力する
[ -f test.txt ] && echo "test"
# test.txtがなければ、textと出力する
[ -f test.txt ] || echo "test"
# ifをこのようにも書ける
if [ "$1" = "test" ] && [ "$2" = test ]; then
echo "test"
fi
# $?でコマンドの終了ステータスを取得(入力0、標準出力1、標準エラー2)
# grepやlsなどのコマンドは、すべて終了時に終了ステータスが排出される
ls /test/
echo "status = $?"
# 自作のシェルスクリプトも同じように終了ステータスを出力できる
# 終了ステータス1で終了する場合
# 何も指定しない場合は最後に実行されたコマンドの終了ステータスになる
exit 1
# この後のコマンドは実行されない(エラー処理などに使用)
# forの使い方
# a、b、cと出力されるサンプル
for list in a b c
do
echo $list
done
# 数値列を扱う例
# seqという数値列を順に出力するコマンドを使用する
for i in $(seq 1 5)
do
echo $i
done
# すべてのコマンドライン引数をechoする例
for param in "$@"
do
echo $param
done
# caseの使い方
case "$1" in
*.txt)
echo 1
;;
*.js|*.css)
# |でorを示す
echo 2
;;
*)
# それ以外を示す
;;
esac
# while
i=10
while [ "$i" -le 10 ]
do
echo "$i"
# 算術式展開を利用
# i=`expr $i + 2`よりもexprという外部コマンドを使用しないため高速
i=$((i + 2))
done
# シェル関数
func ()
{
echo 'test'
# 終了ステータスを指定
# 何も指定しない場合は最後に実行されたコマンドの終了ステータスになる
return 1
# この後のコマンドは実行されない(エラー処理などに使用)
}
# シェル関数を実行
func
シェルスクリプトのサンプル
$ vi sample.sh
// #!/bin/bash はファイルの先頭が「#!」であれば、その後ろのコマンド「/bin/bash」を実行するという意味。つまりbashで実行するという意味になる。
// 「#!」はシバン、あるいはシェバンと呼ばれる
------------ホームディレクトリのファイル使用容量を表示------------
#!/bin/bash
du -h ~ | tail -n 1
------------------------
// 実行権限を付与
$ chmod +x sample.sh
// シェルスクリプトの実行
$ ./sample.sh
// シバンがないシェルスクリプトの場合はsourceコマンド(ファイルからコマンドを読み込んで実行)を使う(この場合実行権限は不要)
$ source ./sample.sh
// bashにおいては、「.」コマンドとsourceコマンドは一緒のため、同じ実行結果となる
$ . ./sample.sh
// シバンがない場合、シェルを指定しても同じ動作となる
$ bash ./sample.sh
sourceコマンドの場合は現在のシェルで実行されるため、エイリアスの設定などは引き継がれるが、シェルスクリプトをそのまま実行した場合などはサブシェル(現在のシェルから新しく起動される子プロセスのシェル)で実行されるため、エイリアスの設定などは引き継がれずエラーとなることがあるため注意。
シェルスクリプトのTIPS
IFS(Internal Field Separator)の変更
IFSは環境変数で、bashが単語の区切りとして解釈する文字が格納されている。
IFSのデフォルト値はスペースとタブ、改行の3つである。
これは通常の環境変数のように変更可能だが、それ以降のコマンドにも影響するため、IFSを変更後にすぐにリセットすることが望ましい。
_IFS=$IFS
IFS=$'\n'
〜〜〜〜
IFS=$_IFS
~/.bash_profileにかかれているやつ
if [ -f ~/.bashrc ]; then
source ~/.bashrc
fi
コマンドとしてひと通りの機能があるスクリプト
#!/bin/bash
usage()
{
cat << END
Usage: ヒアドキュメントでヘルプを記述
END
}
if [ "$1" = "error" ]; then
# エラーがある場合は標準エラーを出して、終了ステータスを2で終了
echo 'error' 1>&2
exit 2
fi
シェルスクリプトを書いたらすること
自分のシェルスクリプト置き場を作成し、その場所をサーチパスに登録する(登録しないとパスを指定しなければならなくなる)。
// シェルスクリプト置き場を作成(~/bin に作るのが慣例)
$ mkdir ~/bin
// サーチパスに~/binを追加
$ vi ~/.bash_profile
---------
# /etc/profileに記述されている$PATHの末尾に~/binを追加
PATH="$PATH:~/bin"
---------
// 反映
$ source ~/.bash_profile
// ~/bin/test.shがある場合は下記のように実行できるようになる
$ test.sh