topページ / Shell Script
Shell ScriptはLinuxやUNIXで使用される簡単で強力なスクリプト言語である。このページではその書き方などについて説明する。
以下のコマンドで起動する。
$ vi
ファイル名を指定した場合はファイルを開く。
viは起動した直後、文字の挿入ができないモードとなっている。これをコマンドモードという。終了するときは、コマンドモードで「:q」とタイプし、Enterを押す。ファイルを編集して、セーブせずに終了したい場合は「:q!」とする。
カーソルキーが使える場合もあるが、基本はアルファベットキーによる移動である。
なお、このキー操作に慣れておけば、nethackというゲームで遊ぶときも、キャラクタ移動にそれほど困らないはずである(あちらは斜め移動もあるが・・・)。
タイプした文字がそのまま挿入できるモードを挿入モードという。vi起動時はコマンドモードであるため、ファイルの編集をするには挿入モードにしなければならない。
コマンドモードから挿入モードへの切り替えはいくらか方法があるが、ここでは代表的なものを紹介する。
要は、vi起動後、iキーを押せば挿入モードになるのである。
また、挿入モードからコマンドモードに切り替えるときはESCキーを押す。
DelキーやBSキーが使えることもあるが、コマンドモードでxキーを押して消すのが基本である。viでは文字の挿入以外はほとんどの機能をコマンドモードでこなすことになる。
また、コマンドモードでddとタイプするとその行が消去される。
アンドゥはコマンドモードでuをタイプする。リドゥは「:redo」とタイプしてエンターを押すか、[Ctrl]-rをタイプする。
コマンドモードで以下のコマンドをタイプする。
コマンドモードで「:w」とタイプし、エンターを押す。別名で保存する場合や新規作成の場合は「:w [ファイル名]」とファイル名を指定する。
コマンドモードで以下のコマンドをタイプする。
なお、検索ワードを省略した場合は前回の検索ワードで検索する。
コマンドモードで「:split」または「:vsplit」とタイプし、エンターキーを押す。splitは上下に分割、vsplitは左右に分割する。
また、「:split [ファイル名]」、「:vsplit [ファイル名]」とファイル名を指定すると、指定したファイルを分割したウインドウで開く。
ウインドウ間の移動は、[Ctrl]+w [Ctrl]+w、又は[Ctrl]+w 方向で移動できる。
分割したウインドウを閉じるときは「:q」、「:q!」コマンドを使う。
コマンドモードでqキーを押した後、適当なキーを押すと、マクロの記録が始まる。
もう一度コマンドモードでqを押して記録を終了するまでの動作が記録される。
コマンドモードで@キーを押した後、記録したときに押したキーを押すと、記録した動作が実行される。
... こんなもんでいいかな?
そこそこ集まっているコマンドのページはこちら。
コマンドの入力、出力を<、>で制御できる。
ディレクトリの中身をファイルに出力するには次のようにする。
$ ls > [ファイル名]
ファイルの中身をcatするには、
$ cat < [ファイル名]
とする。catは第一引数の中身を表示するので、この場合「cat [ファイル名]」としても同じ結果になる。なお、逆の
$ [ファイル名] > cat
とすると、エラーになる。[ファイル名]はコマンドではないので当然だが。
なお、「>>」で、ファイルの最後に追加することができる。
コマンドの実行結果を別のコマンドに渡すにはパイプライン「|」を使用する。
次のコマンドは一画面で表示し切れないps auxの実行結果をlessに渡して、確認できるようにしたもの。
$ ps aux | less
rootが含まれるもののみを表示するために、grepコマンドをはさむと、次のようになる。
$ ps aux | grep root | less
エディタでファイルを作成し、次のように入力する。
#!/bin/bash echo Hello World
#!/bin/bashは「bashを使うぞ」という宣言。
echoは続く文字列を表示するコマンド。
ファイルの実行権限を変更して実行する。
$ chmod 700 [ファイル名] $ ./[ファイル名] Hello World
Hello Worldと表示されたら成功。
envコマンドで確認できる環境変数を使用するには$[環境変数]とすればよい。
#!/bin/bash echo Home=$HOME
このスクリプトでは自分のホームディレクトリが、「Home=ホームディレクトリ」のように表示される。
$[番号]で、引数が取得できる。$0はコマンド自体、$1から、コマンドに続く引数が取得できる。
#!/bin/bash echo ---$1の中身--- ls $1
スクリプトに続けてディレクトリを指定すると、ディレクトリの中身を表示するスクリプト。
引数の数を調べるには、$#とする。引数がない場合、$#は0となる。
if ~ fiで条件分岐ができる。
if [ 条件 ] then [条件を満たしたときの処理] fi
インデントは見やすくするためにつけているだけであり、無くてもOK。
条件の指定の仕方は以下の通り
次のスクリプトでは、引数が1つ以上あれば、第一引数の値を表示する。
#!/bin/bash if [ $# -ge 1 ] then echo $1 fi
括弧と条件の間の空白は必要。無いとエラーになる。
文字列比較の場合は以下の条件を指定する。aとbは比較対象文字列。
次のスクリプトは、第一引数が「abc」であればそれを表示する。
#!/bin/bash if [ $# -ge 1 ] then if [ $1 = "abc" ] then echo $1 fi fi
また、ファイルに対する判定も行うことができる。
次のスクリプトは、ファイル名を指定し、それが存在したら表示する。
#!/bin/bash if [ $# -ge 1 ] then if [ -s $1 ] then echo $1 fi fi
ディレクトリかどうかをチェックするには次のようにする。
#!/bin/bash if [ $# -ge 1 ] then if [ -d $1 ] then echo $1 fi fi
条件を満たさなかった場合の処理はelseで書くことができる。
if [ 条件 ] then [条件を満たしたときの処理] else [条件を満たさなかったときの処理] fi
次のスクリプトはファイルであれば「file: [ファイル名]」を、ディレクトリであれば「dir: [ファイル名]」を表示する。
#!/bin/bash if [ $# -ge 1 ] then if [ -f $1 ] then echo file: $1 else if [-d $1 ] then echo dir: $1 fi fi fi
elseの場合に再度条件分岐をするには上の方法でもよいが、elifを使うことができる。
if [ 条件1 ] then [条件1を満たしたときの処理] elif [ 条件2 ] [条件2を満たしたときの処理] # .... 省略 fi
上のスクリプトを書き直すとつぎのようになる。
#!/bin/bash if [ $# -ge 1 ] then if [ -f $1 ] then echo file: $1 elif [ -d $1 ] then echo dir: $1 fi fi
なお、条件式を複数つなげる必要がある場合はcase~esacが使用できる。
case $[変数] in [パターン]) [パターンに一致したら実行する処理] [パターンに一致したら実行する処理] ......... [パターンに一致したら実行する処理];; [パターン]) [パターンに一致したら実行する処理] [パターンに一致したら実行する処理] ......... [パターンに一致したら実行する処理];; # .... 省略 esac
パターンには数字や文字列が指定できる。-fなどを指定してファイルの存在チェックなどはできない。
パターンに*を指定したら上記どれにも一致しなかったときの処理を設定する。(C言語でいうdefault:の役割。)
以下、使用してみた例。2つのパターンを用意しておき(パターン1=abc、パターン2=def)、引数がパターンに一致したら「pattern1」などというように表示した後に引数を表示するスクリプト。一致しなかったら「default」と表示される。
#!/bin/bash if [ $# -ge 1 ] then case $1 in "abc") echo pattern1 echo $1;; "def") echo pattern2 echo $1;; *) echo default echo $1;; esac fi
変数は次のように定義して、使用する。
#!/bin/bash a=1 echo $a a=`expr $a + 5` echo $a a=`expr $a \* 5` echo $a
aが変数。代入以外では$aとする。exprは計算結果を返す。掛け算はワイルドカードと区別するために\*とする。また、exprを囲んでいるのは「'」ではなく、「`」であることに注意。
コマンドの実行結果を返すときは「`」で囲む。
lsの結果をaに格納し、表示する例
#!/bin/bash a=`ls` echo $a
ループはforループとwhileループが使える。
for (( [初期条件] ; [繰り返し条件] ; [ループ時処理 )) do [処理] done
while [ 繰り返し条件 ] do [処理] done
forループの繰り返し条件は「==」や「<」などの記号を使うのに対し、whileでは「-eq」や「-lt」をつかうのに注意。
次のスクリプトはともに1から9までを表示する。
#!/bin/bash for (( a = 1; a < 10; a++ )) do echo $a done
#!/bin/bash a=1 while [ $a -lt 10 ] do echo $a a=`expr $a + 1` done
forではセットする値リストを使うこともできる。リストの値が一つ一つ変数にセットされ、処理が行われる。
for [変数] in [値リスト] do [処理] done
以下、2,4,6,8,99,AAを表示するスクリプト
#!/bin/bash for a in 2 4 6 8 99 "AA" do echo $a done
カレントディレクトリの全ファイルを調べ、ファイルであれば「file: [ファイル名]」を、ディレクトリであれば「dir : [ファイル名]」を表示するスクリプト。
#!/bin/bash b=`ls` for a in $b do if [ -f $a ] then echo file: $a elif [ -d $a ] then echo dir : $a fi done