オペレーティングシステム2

情報工学科 3年生対象 専門科目
システムプログラミング
第4回
シェルスクリプト
情報工学科
篠埜 功
シェルスクリプト
• シェルに対する命令をファイルに記述したもの
• シェルとは
– コマンドインタプリタ。UNIX系OSではシェルはユ
ーザプログラムであり、自分でシェルを作成する
こともできる。
シェル(/bin/sh)に直接打ち込む例
[sasano@oli004 ~]$ sh
sh-2.05b$ A=ls
sh-2.05b$ $A
<lsの実行結果>
sh-2.05b$
シェルスクリプトは、シェル(通常
は/bin/sh)に対する命令列をファ
イルに格納したものである。ここ
ではファイルに入れずにシェル
(/bin/sh)上で直接実行してみる。
(補足) shと打つことによって、shというファイルが環境変数
PATHに入っているディレクトリから検索され、その結果
/bin/shが見つかり、それが実行される。
A=ls などのように、変数名=文字列
の形で、変数を定義できる。=の前後にスペースを入れて
はいけない。スペースを入れると、この場合、Aをコマンド
名として解釈しようとしてcommand not foundになる。
変数の値の参照は、$変数名とすればよい。
(参考) /bin/tcshの場合
[sasano@oli004 4kai]$ set A=ls
[sasano@oli004 4kai]$ $A
<lsの実行結果が表示される>
[sasano@oli004 4kai]$
/bin/tcsh では、上記のように、set A=lsの形で、set
コマンドを用いてシェル変数を定義する。(ここでは=
の前後にスペースがあってもよい。)
シェル変数の一覧は
$ set
で画面に表示される。(shでもsetで一覧表示。)
環境変数
/bin/shや/bin/bashの場合:
$ export シェル変数名
のようにすることにより、シェル変数が同一の変数名で環境変数となる。
たとえば、
$ A=test
$ export A
など。環境変数の一覧は
$ printenv
で表示される。個々の環境変数の値は
$ printenv A
のように、環境変数名をprintenvコマンドの引数に与えると表示される。
/bin/tcshの場合:
$ setenv A test
のように、setenvコマンドを用いる。(=はないことに注意)
環境変数一覧、個々の値の表示については/bin/shと同じ。環境変数の
値も$環境変数名で参照できるが、同じ名前のシェル変数がある場合、
そちらが優先される。
環境変数の例
dateコマンド(日時の表示)を実行すると
[sasano@oli004 4kai]$ date
2009年 10月 6日 火曜日 13:45:42 JST
のようになるが、
[sasano@oli004 4kai]$ setenv LANG C
のようにすると、
[sasano@oli004 4kai]$ date
Tue Oct 6 13:47:27 JST 2009
のように英語表示になる。
(/bin/shの場合は、LANG=Cとしてからdateを実行
すればよい)
シェル変数の例
PATH, HOME, USER, HOSTNAMEなどのシェル変数が
通常使われている。
$ echo $PATH
$ echo $HOME
$ echo $USER
$ echo $HOSTNAME
などで確認できる。
/bin/shでも/bin/tcshでも同じ。
シェルスクリプト
• ファイルにシェルに対する命令(スクリプト)を書いた
もの。
• 1行目に#!/bin/sh と書く。これによって、/bin/shがス
クリプトを実行することになる。
– #!/bin/bash, #!/bin/tcshなど、他のシェルを指定し
てもよいが、その場合はスクリプトの書き方は異な
る。
• ファイルの属性を、実行を許可するように変更する必
要がある。
$ chmod 755 test.sh
などのようにして変更できる。
例1(打ち込んで確認)
(1)以下を中身とするtest1.shというファイルを作成
#!/bin/sh
ls -l
(2)ファイルの属性を変更
$ chmod 755 test1.sh
(3)実行
$ ./test1.sh
これによって、ls –lが実行される。あるいは、
$ /bin/sh test1.sh
でもよい。
(4) カレントディレクトリのファイルリストが表示されることを
確認。
シェル変数の使用(打ち込んで確認)
(1)以下を中身とするtest2.shというファイルを作成
#!/bin/sh
A=ls
B=-l
$A $B
(2)ファイルの属性を変更
$ chmod 755 test2.sh
(3) 実行
$ ./test2.sh
(4) カレントディレクトリのファイルリストが表示されるこ
とを確認。(例1と同じ)
for文(例1)(打ち込んで確認)
#!/bin/sh
for i in 1 2 4
do
echo $i
done
1
2
4
と表示されればOK。
echoは引数に与えられた文字列
を表示するコマンド。$iが文字列
に展開されてから表示される。
for文の構文、意味
構文
for variable in wordlists; do commands; done
wordlists: 要素をスペースかタブで区切る。
commands: コマンドをセミコロンで区切る。
意味
wordlistsの要素を左から順番に変数variableに代
入し、commandsを実行する。
セミコロンは改行で置き換えてよい。
for文はコマンドであり、コマンドが書けるところには自由に書くこ
とができる。例えばfor文の本体部分にfor文を書いてもよい。
for文の例2(打ち込んで確認)
#!/bin/sh
for D in `date`
do
echo $D
done
バッククオート`でコマンドを
囲むと、その部分がコマン
ドの実行結果で置き換えら
れる。
dateコマンドの出力結果に
はスペースが含まれており、
スペースで区切られた一つ
一つがDに代入され、echo
で1つずつ表示される。
for文の例3(打ち込んで確認)
#!/bin/sh
for L in *
do
echo $L
done
*はカレントディレクトリの
ファイルがスペースで区切
られたものに展開される。
$ echo *
で確認できる。
Lにはカレントディレクトリの
ファイル名が一つずつ代入さ
れ、それがechoで表示され
る。
for文の例4(打ち込んで確認)
#!/bin/sh
for F in *
do
cp $F $F.bak
done
Fにはカレントディレクトリの
ファイルのファイル名が一つ
ずつ代入され、それがcp
で.bakつきのファイルにコ
ピーされる。
for文の例5(打ち込んで確認)
#!/bin/sh
for F in *.c
do
echo $F
cp $F $F.bak
done
第一回目に書いた
シェルスクリプトは、
上記のシェルスクリプ
トの最後にexit 0を加
えたもの。
*.cは、カレントディレクトリ
において、ファイル名の最
後の部分が.cになっている
ファイルのファイル名がス
ペースで区切られたものに
展開される。
Fにはカレントディレクトリ
の.cで終わるファイル名が一
つずつ代入され、それが
echoで表示されたの
ち、.bakつきのファイルにコ
ピーされる。
構文
if文
if commands; then commands; [elif commands;
then commands;]… [else commands;] fi
commands: コマンドをセミコロンで区切ったもの
[ ] はオプション(なくてもよいという意味)。
意味
if の隣に書かれたcommands(の最後のコマンド)の
終了statusが0ならthenパートを実行。そうでなけれ
ばelif以下、あるいはelseパートを(もしあれば)実行。
セミコロンは改行で置き換えてよい。
if文はコマンドであり、コマンドが書けるところには自由に書くこと
ができる。例えばif文のelseパートにif文を書いてもよい。
終了status
コマンドは終了statusを返す。
シェルスクリプトではexit 0 等、exitの右に書く数によって
終了statusを指定する。
Cのプログラムでは、main関数のreturn文あるいはexitシ
ステムコールの引数によって終了statusを指定する。
コマンドの終了statusはシェルが受け取り、$?という変数
に保持している。
(例)
$ ls aaa
$ echo $?
もしaaaというファイルがなければlsコマンドの終了status
が1になっている。
if文の例1(打ち込んで確認)
#!/bin/sh
if test $1 -le $2
then
echo $1 is less than or equal to $2.
else
echo $1 is greater than $2.
fi
testは比較などさまざまな判定を行うコマンド。オ
プションによりさまざまな判定が行える。
test arg1 –le arg2 は、arg1がarg2より小さいか
どうか判定。
$1はシェルスクリプトの1番目の引数、
$2はシェルスクリプトの2番目の引数を表す。
if文の例2(打ち込んで確認)
#!/bin/sh
if diff $1 $2 > /dev/null
then
echo No differences were found between $1 and $2.
else
echo Some differences were found between $1 and $2.
fi
diffは2つのファイルの比較を行うコマンド。
終了statusは、同じとき0, 異なるとき1である。
diffコマンドの標準出力への出力は/dev/nullへリダイレクトさ
れるので捨てられる。(リダイレクトについて後日解説する)
testコマンドについて
testコマンドは大小比較などさまざまな判定に使われる。
数値比較、文字列比較、ファイル形式の判定、ファイルの
修正時刻の比較などがある。さらに、条件をand, or, notで
組み合わせることもできる。
testコマンドは非常によく使われるので略記法がある。
test …は [ … ] と略記してよい。
例えば、test $1 –le $2は、[ $1 –le $2 ]と書ける。
[の次の空白と、]の手前の空白は省けないので注意。
if文の例3(打ち込んで確認)
#!/bin/sh
if [ $1 -le $2 ]
then
echo $1 is less than or equal to $2.
else
echo $1 is greater than $2.
fi
例1におけるtest $1 –le $2を[ $1 –le $2 ]で置き
換えたもの。
ifコマンドについての補足1
ifコマンドはネストしてよい。例えば、elseパート有りのifコマンドを
ネストして、
if …
then
…
else
if …
then
…
else
…
fi
fi
のような形で使える。これは外側のifコマンドにおけるelseパート
のコマンド(赤字の部分)がifコマンドになっているということである。
ifコマンドについての補足2
さきほどのifコマンドのネストは
if …
then
…
elif …
then
…
else
…
fi
のように書いてもよい。この場合はifコマンドのネストで
はなく、1つのifコマンドである。