1. シェルとは

    クルミを思い浮かべてください(貝でもかまいません。)。UNIXの本体はカーネルと言われる核(クルミの中身)の部分で、シェルは、コマンドラインのユーザーインターフェースを担う部分(クルミの殻)にあたります。MS-DOSのコマンドプロンプトやWindows95/NTのMS-DOSプロンプトと同じだと思っていただいていいでしょう。(WindowsのExplorerは、GUIタイプのシェルと言ってもいいかもしれません。)

    UNIXの場合、このシェルを変える事ができます。SVRの場合は、sh、ksh、cshが標準で搭載されています。

    (MS-DOSでもシェル(COMMAND.COM)を変えることはできるんですよ。知ってました?)

    sh しぇる or
    びー・しぇる
    Bourneシェル。ベル研のSteve Bourneによって開発された最初のシェル。全てのUNIXに標準で搭載されています。作者の名前から「びー・しぇる」と呼ばれます。シェルスクリプトはBシェルで記述されることが多いようです。
    csh しー・しぇる Cシェル。Bill Joyによって開発された。BSDシステム標準のシェル。シェルスクリプトの文法がC言語と似ている事からCシェルと名づけられました。
    ksh けー・しぇる Kornシェル。ベル研のDavid KornによってCシェルと対抗するかたちで作成されたSVRシステムの標準シェル。Bシェルを拡張した形になっているので、shのシェルスクリプトが通ります。

    このほかにも、cshを拡張したtcsh、tcsh、kshを拡張したzsh、GNUのbashなどがあります。

    UNIXにログオンしたときに、プロンプトに$が出ていたらB系のシェルで、%が出ていたらC系のシェルです。ただし、ルートで入っていると#になっています。また、設定でプロンプトを変えていたらこうはなりません。

    ログインしたときのシェルは、システム権限のユーザーからusermodコマンドで変更できます。

  2. シェルのコマンド行の構文

    シェルのコマンド行は、下記のような構文になっています。

    シェルのコマンド行の構文

    コマンド行は、必ずしも1行で入力する必要はありません。適当なところで\(またはバックスラッシュ\)を入力して改行を入れると次の行に続きを入力できます(¥の直後に改行してください。)。また、シェルが制御文が終わっていないと判断した場合も¥がなくても自動的に複数行に入力できます。

    1. 基本コマンド

      コマンド名 [オプション] [引数]...

      コマンド名の種類としては、下記のようなものがあります。

      • シェル機能コマンド

        cd pwdなどプロセスを起動するのではなく、シェル内部で処理される機能。

      • シェル制御コマンド

        for do done ifなど、シェル内部で処理されるシェルの制御文。

      • エイリアス

        コマンドの別名。タイプ量を減らしたり、コマンドを覚えやすくするために登録された文字列。
        シェルによって、元のコマンドに展開されて実行されます。

      • 実行ファイル名

        プログラムが格納されたファイル。プログラムはシェル、awk,perlなどのスクリプトでもよい。

      オプションは、プログラムの動作を指定するもので、引数は動作の対象を指定するものです。

      引数としてファイルを指定する場合に、(多くの場合)ワイルドカードを指定する事が出来ます。ワイルドカードが指定された場合、シェルがワイルドカードを展開して、ファイル名にしてコマンドに引き渡します。

      • ワイルドカード

        ? 任意の1文字
        * 0個以上の文字
        [文字リスト] 文字リストに含まれる任意の1文字。
        [abcd]はa,b,c,dのいづれかと一致するもの。
        -を使って範囲指定も出来ます。
        [a-d]は、[abcd]と同じです。
        [!文字リスト] 文字リストに含まれない任意の1文字。
        -を使った範囲指定も出来ます。
        [!a-zA-Z]はアルファベット以外と一致します。

      その外にも下記のような引数の補助機能があります。

      • チルダ

        ~
        ~ユーザー名

        ~(ちるだ)は、ホームディレクトリに置き換わります。Bシェルにはない機能です。

        $ echo ~
        現ユーザーのホームディレクトリ名表示

        $ echo ~www
        wwwユーザーのホームディレクトリ名の表示

      • コマンド置換

        `コマンド`

        逆引用符(``)を使用すると、コマンドの標準出力への出力内容をコマンド行に含める事ができます。

        $ echo `pwd`
        /opt

        Kシェルでは、同様の機能で、$(コマンド)があります。
        また、$(<ファイル名)は、`cat ファイル名`と同等です。catを起動しないので速いようです。

      • 変数置換

        $変数名
        ${変数名}

        環境変数(Cシェルのシェル変数を含む)の内容で置換します。変数については後で説明します。

      • 引用符

        "文字列"
        '文字列'

        ワイルドカード、コマンド連結記号、空白、タブ、変数参照記号など、シェル制御文字をコマンドの引数として入力する場合、引用符で囲むかエスケープ文字を前に入力します。

        シェルで使用できる引用符には、二重引用符("")と一重引用符('')があります。

        これらには、次の違いがあります。○は処理が行われ、×は処理されません。

        ワイルドカード 変数置換 コマンド置換
        二重引用符 ×
        一重引用符 × × ×

        $ echo "*.*" '*.*'
        *.* *.*
        $ echo "$TERM" '$TERM'
        vt100 $TERM
        $ echo "`pwd`" '`pwd`'
        /tmp `pwd`

      • エスケープ文字

        \文字

        引用符の外側で、1文字の機能を打ち消すには、エスケープ文字を前に入力します。

        \は、欧文フォントシステムでは、バックスラッシュ(\)として表示されます。

        例)引用符の機能を抑制
        $ echo \"STRING\"

        \の直後で改行を入力すると改行がエスケープされるため、複数行に渡ってコマンドを入力することができます。

    2. リダイレクト

      UNIXのコマンドの多くは、標準入力からデータを読み、結果を標準出力にだすようになっています。通常、標準入力はキーボードに、標準出力は画面に設定されていますが、リダイレクトを使用すると、この割り当てを変更することができます。

      シェルによって、リダイレクトの書き方に若干の違いがありますので、cshとkshについて、説明します。

      Kシェル Cシェル 説明
      標準入力

      < ファイル

      同左 標準入力をファイルから読みます。
      標準出力

      > ファイル

      同左 標準出力をファイルに変えます。
      ファイルが既にあれば上書きします。

      >> ファイル

      同左 標準出力をファイルに変えます。
      ファイルがすでにあれば追加します。
      エラー出力

      2> ファイル

      >& ファイル エラー出力をファイルに変えます。
      ファイルがすでにあれば上書きします。

      2>> ファイル

      >>& ファイル エラー出力をファイルに変えます。
      ファイルがすでにあれば追加します。
      ファイルハンドル
      の切り替え

      ハンドル番号> ファイル

        ファイルハンドルの出力をファイルに変えます。
      ファイルがすでにあれば上書きします。
      標準出力のハンドル番号は1なので、
      「1> ファイル」は「> ファイル」と同じです。

      ハンドル番号>> ファイル

        ファイルハンドルの出力をファイルに変えます。
      ファイルがすでにあれば追加します。
      出力先を他のハンドルと同じにする。

      ハンドル番号> &ハンドル番号

        > out.txt 2>&1とすると、標準出力、エラー出力ともにout.txtに出力されます。
      ヒアドキュメント <<終了行
      入力として渡す
      ドキュメントの内容。

      終了行
      同左

      <<の直後に指定された文字列が行の先頭に現れるまでを、
      標準入力とします。

      cat <<END
      この部分が、
      標準入力にわたされます。
      END

      を実行すると

      この部分が、
      標準入力にわたされます。

      と表示されます。

      パイプ

      |

      同左 前のコマンドの標準出力を後のコマンドの標準入力とします。
      パイプはコマンド連結記号なのですが、リダイレクトの機能ももっていますので、ここでも説明しておきます。

    3. コマンド連結記号

      コマンド連結記号を使うと複数のコマンドを連結できます。

      |

      パイプ。前のコマンドの標準出力を次のコマンドの標準入力とします。

      &

      前のコマンドと次のコマンドを並列に実行します(バックグラウンド)。
      &は、コマンドを連結せずに単独でも使用でき、バックグランドジョブとして起動できます。

      &&

      前のコマンドが成功(終了ステータスが0)であれば、次のコマンドを実行します。

      ||

      前のコマンドが成功(終了ステータス0)でなければ、次のコマンドを実行します。

      ;

      コマンドを順番に実行します。;の代わりに改行があるのと同じ。

    4. コマンドのグループ化

      コマンド群を( )でまとめることが出来ます。
      まとめるというのは、

      • リダイレクトはコマンド全体を対象に働きます。

        $(ls /tmp ; ls /usr ) > foo.txt

      • コマンドは、独立した環境で動きます。つまり、( )内で設定した環境変数やカレントディレクトリの変更は、( )を脱出したあとの環境に影響しません。

        $pwd
        /usr/foo
        $(cd /tmp;pwd)
        /tmp
        $pwd
        /usr/foo
        $

        ・・・もとのディレクトリ
        ・・・( )内でディレクトリ変更


        ・・・( )を抜けると前と同じディレクトリ

  3. コマンド行補助機能

    kshやcshには、以前入力したコマンドを再実行したり、入れ間違ったコマンドを修正したりする機能があります。

    機能 Kシェル Cシェル

    ファイル名の入力補助機能

    VISUAL変数にemacsまたはgemacsモードが設定されている必要があります。

    $ VISUAL=emacs

    ファイル名の途中まで入れて、[ESC][ESC](エスケープキーを2回)と入力すると存在しているファイル名が入力位置へ挿入されます。

    文字列[ESC][ESC]

    目的のファイルでない場合は、さらに[ESC]を押してください。

    変数filecが定義されている必要があります。

    % set filec

    文字列に続けて[ESC]キーを押すとファイルが補完されます。次候補はさらに[ESC]です。

    文字列[ESC]

    上記のように本には、書いてあったのですが、どちらも複数候補ある場合は補完されませんでした。
    また、次候補も出てきませんでした(?????)。

    ファイル名一覧機能

    VISUAL変数にemacsまたはgemacsモードが設定されている必要があります。

    $ VISUAL=emacs

    ファイル名の途中まで入れて、[ESC]=と入力すると名前が一致するファイル名の一覧が表示されます。

    [文字列][ESC][ESC]

    変数filecが定義されている必要があります。

    % set filec

    文字列に続けてCtrl+Dを押すとファイル一覧が表示されます。

    [文字列]Ctrl-D

    行編集機能

    ■EMACSモード

    $ VISUAL=emacs の場合

    カーソル← CTRL-B
    カーソル→ CTRL-F
    行頭 CTRL-A
    行末 CTRL-E
    デリート CTRL-D
    バックスペース Back space(端末設定によって違うかも)
    カーソルから行末まで削除 CTRL-K

    詳しくは、emacsのコマンドを調べてください。

    ■Viモード

    $ VISUAL=vi の場合

    まず、コマンド入力モードに入るために[ESC]を押した後次の操作が可能になります。

    カーソル← h または b
    カーソル→ l または スペース
    行頭 0 または ^
    行末 $
    デリート x
    カーソルから行末まで削除 D
    カーソル前に文字挿入 i
    カーソル後に文字追加 a
    行頭に文字挿入 I
    行末に文字追加 A
    カーソル位置から上書き R

    詳しくは、VIのコマンドを調べてください。

     

    コマンド履歴

    ■履歴の表示

    $ history

    で番号付きのコマンド履歴一覧を参照できます。
    (historyは、fc -lのエイリアスです。)

    ■コマンドの再実行

    $ r [[置換対象文字列]=[置換後文字列]] [履歴番号|コマンドの先頭文字列]

    (rはfc -e -のエイリアスです。)

    例)
    $history
    183 ls /home
    184 ls -l /home
    185 history

    $ r 直前のコマンドの再実行。185が実行される。
    $ r 183 指定した番号のコマンドが実行される。
    $ r ls 指定した文字列と先頭の文字列が一致するものが実行される。
    複数一致する場合は、新しい方
    $ r home=usr ls 一致する文字が置き換えられて実行される。184がls -l /usrになって実行される。
    $ r home=usr 184 同上

    ■コマンドを編集して再実行

    $ fc [履歴番号|コマンドの先頭の文字列]

    以前実行したコマンドを、エディタを使って編集する事もできます。
    編集に使うエディタを環境変数FCEDITで指定します。

    $FCEDIT=vi

    fcだけの場合は、直前に実行したコマンドを編集します。
    ファイルを保存して、エディタを終了するとコマンドが実行されます。
    保存しなかった場合は、実行されません。

    ■行編集機能

    履歴を呼び出す行編集機能として下記があります。

    1. EMACSモード

      $ VISUAL=emacs の場合

      実行履歴の前のコマンドを呼び出し CTRL-P
      実行履歴の次のコマンドを呼び出し CTRL-N
      文字列を含むコマンド行を実行履歴から呼び出し CTRL-R文字列「改行」

    2. Viモード

      $ VISUAL=vi の場合

      コマンド入力モードに入るために[ESC]を押した後次の操作が可能になります。

      コマンド履歴の前のコマンドを呼び出し k または -
      コマンド履歴の次のコマンドを呼び出し j または +
      文字列を含むコマンド行を実行履歴から呼び出し /文字列「改行」

    Cシェルでコマンド履歴の機能を使うには、history変数に履歴バッファの行数を指定しておく必要があります。

    % set history=10

    ■履歴の表示

    % history

    で番号付きのコマンド履歴一覧を参照できます。

    ■コマンド選択

    % !! 直前の処理を選択
    % !履歴番号 コマンド履歴の番号を指定
    % !文字列 コマンド履歴で文字列が先頭一致するコマンドを指定
    % !?文字列? コマンド履歴で文字列を含むコマンドを指定

    Kシェルとちがって、!!などはコマンドではなく置き換えによって実行されます。
    このため、

    % !!

    では直前の処理の再実行となりますが、

    % echo !!

    のような事も可能です(直前のコマンドを表示)。

    ■ワード選択

    また、下記を指定の最後につける事で、コマンドの一部を取り出す事もできます。

    :番号 指定ワード目を取り出す。

    % echo one two three
    % echo !!:2
    two
    (0オリジンです。!!:0はechoになります。)
    :^ 先頭ワード

    % echo one two three
    % echo !!:^
    echo
    :$
    :%

    ■編集コマンド

    「コマンド選択」や「ワード選択」で選択されたコマンドの文字列の置換ができます。

    ・文字列の置換 (:[g]s/検索文字列/置換文字列/)

    例)gなしの場合

    % echo one two three two
    % !!:s/two/2/
    one 2 three two

    例)gありの場合

    % echo one two three two
    % !!:gs/two/2/
    one 2 three 2

    gを付けない場合は、最初に一致した文字だけに作用しますが、gをつけると一致する全ての文字列に作用します。

    検索文字列に正規表現は使えませんが、置換後文字列に&を指定することはできます。&は検索文字列と同じです。

    % echo one two three
    % !!:s/three/& four/
    one two three four

    ・表示のみ行う。表示のみ行う( :p )

    例)

    % echo one two three
    % !!:p
    echo one two three
    % !!:s/two/2/:p
    echo one 2 three

    echo !!:s/two/2/!!:s/two/2/:pの違いは、前者は、echo echo one 2 threeが実行されて、コマンドヒストリーにもこれが入りますが、後者は、echo one 2 threeが入ります。ですから、:pで編集を確認したあと!!とすれば表示した内容の再実行が出来ます。

    ■直前のコマンドの編集

    ^検索文字列^置換文字列

    これは、

    !!:s/検索文字列/置換文字列/

    と等価です。

    ディレクトリ移動補助 cd -

    1つ前にいたディレクトリに移動します。

    pushd ディレクトリ
    pushd +番号
    popd
    popd +番号

    ディレクトリスタックを操作するコマンドです。ディレクトリスタックは、スタック構造になっており、「pushd ディレクトリ」によりスタックにディレクトリがスタックされ、カレントディレクトリもpushdでしたディレクトリになります(スタックの最上位にあるディレクトリがカレントディレクトリになります)。popdを行うと最上位にあるディレクトリがスタックから削除されます。最上位にあるディレクトリがなくなるので、その下のディレクトリがカレントディレクトリになります。

    pushd +1とするとディレクトリスタックの最上位から1つ下にあるディレクトリが最上位(カレントディレクトリ)になり、今までカレントディレクトリだったディレクトリが一番下にロールします。例えば、ディレクトリが a b c d eとスタックされており、(カレントディレクトリがa)で、pushd +3 とすると d e a b c の順番にスタックが変更されます。pupd +番号では、番号で指定された位置にあるディレクトリがディレクトリスタックから削除されます。

  4. コマンドに別名をつける

    コマンドに別名をつける事ができます。
    Kシェル Cシェル
    別名の設定

    alias 別名=置き換え文字列

    例)
    alias ls="ls -aF"
    alias rm="rm -i"

    Kシェルでは、Cシェルのようにaliasで使用しているコマンドの途中に引数を埋め込むことは出来ませんが、シェル関数を使用すると同様の事ができます。

    alias 別名 置き換え文字列

    例)
    alias ls "ls -aF"
    alias rm "rm -i"

    Cシェルでは、!*を置き換え文字列中で使用して別名コマンドの引数とする事ができます。

    例)
    % alias ll 'ls -l \!* | nl'
    % ll /tmp

    この場合、ls -l /tmp | nlが実行されます。

    別名の解除

    unalias 別名...

    例)
    unalias ls rm

    複数指定できます。

    unalias 別名...

    例)
    unalias ls rm

    複数指定できます。
    また、*を指定すると全てのaliasを解除できます。

    unalias *

    別名の一覧 alias alias

  5. 変数

    シェル内では、環境変数と言う変数に文字列や数値を代入できます。環境変数には、シェルから起動したプロセスにも引き継がれるものとシェル内だけで有効な変数があります。Cシェルでは、前者を環境変数、後者をシェル変数と呼んで区別し、設定も別のコマンドで行いますが、Kornシェルでは、どちらも環境変数と呼び、同じコマンドでセットします。ただし、他のプロセスに引き継ぐ変数はexportコマンドで登録します。

    % set ABC 123 ←シェル変数
    % setenv XYZ 123 ←環境変数
    % csh ←子プロセスでcshを起動

    このとき、シェル変数ABCは引き継がれませんが、環境変数XYZは引き継がれます。

    Kシェル Cシェル
    設定

    ■文字列を設定

    変数名=文字列

    =の前後に空白を入れない事。

    変数名=

    とすると空文字が設定されます。

    ■数値を設定

    let 変数名="演算式"
    変数名=$((演算式))

    どちらを使用しても同じです。演算子としては、下記が使えます。演算子の前後には空白が必要です。
    + *
    - /

    ■export

    環境変数をexportすると環境変数が他の起動した他のプロセスへも引き継がれるようになります。

    export 変数名

    exportを使用して変数の値を設定して、exportする事もできます。

    export 変数名=文字列

    ■配列変数

    変数は、要素番号0から始まる1次元の変数として使用できます。正確には「環境変数はすべて配列変数であり、配列要素番号を省略して使用すると配列要素番号0が使用される」と言えます。

    変数名[要素番号]=値

    変数名の後ろに[]をつけて要素番号を指定するだけです。

    set -A 変数名 値.....

    配列要素に一度に値を設定したい場合は、このようにします。

    例)
    $ set -A TEST 1 2 3 4
    $ set
    TEST[0]=1
    TEST[1]=2
    TEST[2]=3
    TEST[3]=4
    $ TEST=5
    $ TEST[2]=100
    $ set
    TEST[0]=5
    TEST[1]=2
    TEST[2]=100
    TEST[3]=4

    ■シェル変数(他のプロセスに引き継がれない変数)の設定

    set シェル変数名[=値]

    ■環境変数(他のプロセスに引き継がれる変数)の設定

    setenv 環境変数名 [値]

    Cシェルでは通常、環境変数は大文字で定義し、シェル変数は小文字で定義する習慣になっていますが、実際の使用にあたっては制限されているわけではありません。

    シェル変数と環境変数に同じ名前の変数名が使用されると、変数参照ではシェル変数が優先されます。

    ただし、次の変数については、互いに連動して動き、どちらかを変更すると他方の内容も変わります。

    値を省略した場合は、空文字が設定されます。

    環境変数 シェル変数
    USER user
    TERM term
    HOME home
    PATH path

    ■数値演算

    @ シェル変数名 代入演算子 式

    シェル変数に式の演算結果を代入します。

    % @ keisan = 1 + 3
    % echo $keisan
    4
    %

    下記の代入演算子が使用できます。

    = += -= *= /= ++ --

    演算子には、下記が使用できます。仕様はC言語に準拠。
    括弧 ()
    ビット反転 ~
    論理否定 !
    積、除、剰余 * / %
    和、差 + -
    シフト << >>
    大小比較 <= >= < >
    文字列比較 == != =~ !~
    ビット積 &
    排他的論理和 ^
    ビット和 |
    論理積 &&
    論理和 ||

    また、次のファイル属性構文も使用できます。この場合、真は1、偽は0として数値化されます。

    読み出し可 -r ファイル名
    書き込み可 -w ファイル名
    実行可 -x ファイル名
    ファイル(またはディレクトリ)が存在 -e ファイル名
    一般ファイル -f ファイル名
    ディレクトリ -d ディレクトリ名

    変数の定義未定義を調べる事もできます。定義されていれば、1、されていなければ0です。

    % ls -l
    合計 0
    -rw-r--r-- 1 euc dba 0 5月 26日 10:02 foo
    % @ fcheck = -f foo
    % @ dcheck = -d foo
    % echo $fcheck $dcheck
    1 0
    %

    $?変数名
    ${?変数名}

    ■配列変数

    Kシェルと異なり、Cシェルでは、要素番号は1から始まります。

    set 変数名=( 値 値.... )

    これにより要素が作成されます。

    set 変数名[要素番号]=値

    Kシェルとは違って、存在していない要素番号に設定する事はできません。 最初にset 変数名=(値 値...)で配列を作成しておいてから、値を変える時に使用します。

    % set TEST=(1 2 3 4 5)
    % set
    TEST (1 2 3 4 5)
    % set TEST[2]=two
    % set
    TEST (1 two 3 4 5)

    削除 unset 変数名...

    ■シェル変数

    unset 変数名...

    ■環境変数

    unsetenv 変数名...

    一覧表示

    ■変数一覧(exportしている変数を含む)

    set

    ■exportしている変数一覧

    export

    ■シェル変数一覧

    set

    ■環境変数一覧

    setenv

    変数の参照

    変数値 $変数名
    変数値 ${変数名}
    変数の文字数 ${#変数名}
    配列変数の要素 ${変数名[要素番号]}
    配列変数の要素の文字数 ${#変数名[要素番号]}
    配列変数の要素数 ${#変数名[*]}
    配列変数の要素全体 ${変数名[*]}

    シェルでは、変数名の前に$を付けると変数の内容を参照する事になります。

    $ echo $TERM
    vt100

    $ echo ${TERM}inal
    vt100inal

    変数参照の変数名の区別がつかないときは、{}で変数名を囲みます。

    Kシェルには、変数の値の一部を取り出すことができます。
    ${変数名#パターン文字列} 変数先頭のパターン文字列(最小一致)を削除した結果を返却
    ${変数名##パターン文字列} 変数先頭のパターン文字列(最大一致)を削除した結果を返却
    ${変数名%パターン文字列} 変数末尾のパターン文字列(最小一致)を削除した結果を返却
    ${変数名%%パターン文字列} 変数末尾のパターン文字列(最大一致)を削除した結果を返却

    例)
    $ echo $PATH /usr/sbin:/usr/ccs/bin:/usr/ucb:.
    $ echo ${PATH#*:}
    /usr/ccs/bin:/usr/ucb:.
    $ echo ${PATH##*:}
    .
    $ echo $PATH
    /usr/sbin:/usr/ccs/bin:/usr/ucb:.
    $ echo ${PATH#*:}
    /usr/ccs/bin:/usr/ucb:.
    $ echo ${PATH##*:}
    .
    $ echo ${PATH%:*}
    /usr/sbin:/usr/ccs/bin:/usr/ucb
    $ echo ${PATH%%:*}
    /usr/sbin

    変数値 $変数名
    変数値 ${変数名}
    配列変数の要素 $変数名[要素番号]
    配列変数の要素 ${変数名[要素番号]}
    配列変数の要素数 ${#変数名}
    配列変数の要素全体 ${変数名}


    Kシェルと微妙に違います。

  6. シェルスクリプト
    1. シェルスクリプトの作成と実行

      コマンドラインで打つ内容をテキストファイルに保存して、そのファイルを実行させることができます(MS−DOSのバッチファイルと同じです)。 MS−DOSの場合は拡張子がbatのファイルがバッチファイルと言うことになっていましたが、UNIXでは、特に決められていません。 特に決められていませんが、他と区別がつかないと不便なので、sh、csh、kshなどの拡張子を付けることが多いようです。

      実行は、

      % /bin/csh ファイル名
      のようにしても可能ですが、実行許可ビットを立てることでも実行できます。

      % cat foo  ←ファイルfooの内容を表示
      echo ファイルfooが実行されました。

      % ls -lF foo
      -rw-r--r-- 1 oracle dba 35 5月 6日 10:38 foo
      ↑実行許可ビットは立っていない
      %/bin/csh foo
      ファイルfooが実行されました。
      ↑ファイルをシェルのパラメータとして起動した場合は実行されるが、
      ↓直接実行させた場合は、実行許可の関係で実行されない。

      % foo
      foo: パーミッションが与えられていません。
      ↑実行許可ビットが立っていないのでエラー
      % chmod +x foo  ←実行許可ビットを立てる
      % ls -lF foo
      -rwxr-xr-x 1 oracle dba 35 5月 6日 10:38 foo*
      ↑実行許可ビットが立った
      % foo
      ファイルfooが実行されました。
      ↑実行できた

      このとき、実行されるシェルは、Kシェルでは、Kシェルが、Cシェルでは、最初の行が#で始まる場合は、Cシェルが、#で始まらない場合はBorneシェルとなります。なお、#以降のその行の文字は、コメントとなります。
      環境変数で指定されたシェル以外のシェルで起動したい場合は、ファイルの先頭行を

      #!シェルへのパス

      とする事で明示的に指定することができます。

      例えば、

      #!/bin/ksh

      のようにします。これは、perlやawk,sedなどでも有効です。

      例)
      % cat foo
      #!/usr/bin/nawk -f
      BEGIN {
      print "Start";
      }
      % foo
      Start

    2. シェルスクリプトを現環境で実行

      シェルスクリプトを起動すると、別のシェルが起動されて、その環境内で実行されます。このため、シェル内で環境変数を変更したり、カレントディレクトリを変更しても親環境には影響しません。逆に、環境変数を設定するために、シェルスクリプトを実行したい場合は、下記のように、現環境内でシェルスクリプトを実行させます。

      Kシェル Cシェル
      . シェルスクリプトファイル名 [引数・・・]

      .(ドット)の後には空白を入れてください。
      source シェルスクリプトファイル名 [引数・・・]

      $ cat samp1.ksh
      #!/usr/bin/ksh
      cd /tmp
      TEST=XYZ
      スクリプト内でディレクトリの変更とシェル変数を変更
      $ echo $TEST
      ABC
      $ pwd
      /usr/akiyama
      実行前の状態
      $ samp1.ksh
      $ echo $TEST
      ABC
      $ pwd
      /usr/akiyama
      普通に起動した場合は変更されない。
      $ . samp1.ksh
      $ echo $TEST
      XYZ
      $ pwd
      /tmp
      現環境で実行した場合は、変更される

    3. シェルスクリプトの引数

      $ シェルスクリプトファイル名 引数1 引数2 引数3 ....
      $ /usr/bin/ksh シェルスクリプト名 引数1 引数2 引数3 ....

      シェルスクリプトの引数は、環境変数$番号に設定されます。
      Kシェル Cシェル 説明
      $0
      ${0}
      $0
      ${0}
      シェルスクリプトの名前
      $n
      ${n}
      $n
      ${n}
      $argv[n]
      ${argv[n]}
      N番目の引数の値
      $#
      ${#}
      $#argv
      ${#argv}
      引数の数

      $nでは、存在しない引数を参照した場合、空文字となりますが、Cシェルのargvでは、存在しない要素番号を指定するとエラーとなります。

      $ cat foo
      #/usr/bin/ksh
      echo $#
      echo $0
      echo $1
      echo $2
      $ foo one two
      2
      foo
      one
      two
      $ ./foo one
      1
      ./foo
      one

      引数を扱うコマンドとして次のものがあります。

      • shift

        shiftは、各引数を前へシフトします。(Bシェル、Kシェル)

        $ cat sample.sh
        echo $# $0 $1 $2 $3
        shift
        echo $# $0 $1 $2 $3
        $ sample.sh A B C D E F
        6 sample.sh A B C
        5 sample.sh B C D

      • getopts

        UNIXでは、通常、オプション文字の前に−または+を付けます。このオプションフラグを分解します。(Kシェル、Bシェル)

        getopts オプション文字リスト 変数名

        ■オプション文字リスト

        オプション文字として有効な文字を指定します。オプションが引数を取る場合は、文字に続けて:を指定します。
        例えば、引数を取らないオプションがa,b,c、引数を取るオプションがx,y,zであれば、

        abcx:y:z:

        のようにします。

        ■変数名

        変数には、オプションとして解釈された文字が格納されます。不明のオプション文字は?が設定されます。


        この他に、次の環境変数が返却されます。

        OPTARG オプションの引数が返される
        OPTIND データ引数が始まる番号を返す

        例)
        $ cat sample.ksh
        #/usr/bin/ksh
        while getopts abcx:y:z: opt
        do
          echo オプション=$opt オプション引数=$OPTARG 引数開始番号=$OPTIND
        done

        while [ $OPTIND -gt 1 ]
        do
          shift
          let OPTIND="$OPTIND - 1"
        done

        while [ $# -ge 1 ]
        do
          echo 引数=$1
          shift
        done

        $ sample.ksh -a -x xargs -abc -e +bc param1 param2
        オプション=a オプション引数= 引数開始番号=2
        オプション=x オプション引数=xargs 引数開始番号=4
        オプション=a オプション引数= 引数開始番号=4
        オプション=b オプション引数= 引数開始番号=4
        オプション=c オプション引数= 引数開始番号=5
        sample.ksh: getopts: e bad option(s)
        オプション=? オプション引数= 引数開始番号=6
        オプション=+b オプション引数= 引数開始番号=6
        オプション=+c オプション引数= 引数開始番号=7
        引数=param1
        引数=param2

    4. 条件式

      シェルの制御文で使用する条件式は、Kシェルでは、

      if [ 条件式 ]
      then
       コマンド
      fi

      のように[]で囲みます。[]と条件式の間にはスペースを入れなければいけません。
      ただし、コマンドの実行結果を条件として取得する場合は、

      if コマンド
      then
       コマンド
      fi

      のようになり、[]で囲みません。コマンドの実行結果をうける場合のコマンドにはシェルスクリプトを指定することも出来ます。このときの返却値はexit(またはreturn)の値となります。

      Cシェルでは、 if(条件式)then
       コマンド
      endif

      のようになります。

      Kシェル Cシェル
      ファイル属性検査
      読み出し可 -r ファイル
      書き込み可 -w ファイル
      実行可 -x ファイル
      ファイルが存在(ディレクトリを含む) -e ファイル
      ファイルが存在し、一般ファイル -f ファイル
      ディレクトリ -d ディレクトリ

      文字列の比較 文字列 != 文字列 文字列 > 文字列
      文字列 < 文字列
      文字列の長さが1以上 -n 文字列
      文字列
      文字列の長さが0 -z 文字列
      文字列の一致 文字列 = 文字列
      文字列の不一致
      文字列の大小関係

      数値の比較 式 -gt 式 式 -le 式 式 -ge 式
      等価 式 -eq 式
      不等価 式 -ne 式
      小さい 式 -lt 式
      大きい
      以下
      以上

      条件の連結
      否定 ! 条件式
      AND 条件式 -a 条件式
      OR 条件式 -o 条件式

      true 真(0)
      false 偽(非0)

      演算子には、下記が使用できます。仕様はC言語に準拠。
      ただし、代入演算子は使えません。
      括弧 ()
      ビット反転 ~
      論理否定 !
      積、除、剰余 * / %
      和、差 + -
      シフト << >>
      大小比較 <= >= < >
      文字列比較 == != =~ !~
      ビット積 &
      排他的論理和 ^
      ビット和 |
      論理積 &&
      論理和 ||

    5. 制御文

      Kシェル Cシェル
      分岐
      if 条件式
      then
       コマンド
        :
      elif 条件式
      then
       コマンド
        :
        :
      else
       コマンド
        :
      fi

      条件式(または条件コマンド)の結果が0(真または正常終了)かどうかで制御を分岐します。elifブロックとelseブロックは省略できます。
      if ( 条件式 ) then
       コマンド
        :
      else if ( 条件式 ) then
       コマンド
        :
        :
      else
       コマンド
        :
      endif

      条件式の結果が正常(非0)かどうかで制御を分岐します。else ifブロックとelseブロックは省略できます。
      規定回数の繰り返し

      for 変数 in 文字列... do
        コマンド
        [break]
        [continue]
      done


      変数に文字列を空白文字毎に区切って、順番に代入し、do〜doneの範囲のコマンドブロックを実行します。
      continueは、doneへ制御を移し、次の文字列の処理に移ります。
      breakは繰り返しから脱出します。

      例1)
      $ cat foo
      for x in 1 2 3
      do
        echo start $x
        if [ $x = "1" ]
        then
          continue
        fi
        if [ $x = "2" ]
        then
          break
        fi
        echo end $x
      done
      $ foo
      start 1
      start 2

      例2)指定ディレクトリのファイルをシフトJISに変換して/tmpディレクトリにコピー
      #/usr/bin/ksh
      for x in `ls $1`
      do
        euctosj $x > /tmp/$x
      done

      foreach 変数名 (文字列...)
        コマンド
        [break]
        [continue]
      end


      変数に文字列を空白文字毎に区切って順番に代入し、endまでのコマンドブロックを繰り返し実行します。
      continueは、endへ制御を移し、次の文字列の処理に移ります。
      breakは繰り返しから脱出します。

      例1)
      % cat foo #/usr/bin/csh
      foreach x ( 1 2 3 )
        echo start $x
        if ( $x == "1" ) then
          continue
        endif
        if ( $x == "2" ) then
          break
        endif
        echo end $x
      end

      例2)
      #/usr/bin/csh
      foreach x ( `ls $1` )
        euctosj $x > /tmp/$x
      end

      実行結果はKシェルと同じです。

      条件繰返し

      ■while
      while 条件式
      do
       コマンド
       [break]
       [continue]
        done


      条件式(または条件コマンド)の結果が0(真または正常終了)の間、do〜done間のコマンドブロックを繰り返し実行します。


      ■until
      until 条件式
      do
       コマンド
       [break]
       [continue]
        done

      条件式(または条件コマンド)の結果が0(真または正常終了)になるまで、do〜done間のコマンドブロックを繰り返し実行します。

      例)
      while [`date +%H%M` -le $1 ]
      do
        date
        sleep 60
      done

      while ( 条件式 )
       コマンド
       [break]
       [continue]
        end

      条件式のステータスが非0(正常)の間、endまでを繰り返し実行します。

      例)
      while (^ `date +%H%M` -le $1 ]
      do
        date
        sleep 60
      done
      メニュー選択
      select 変数 in 文字列 do
       コマンド
       [break]
       [continue]
        done

      文字列のメニューリストを番号付きで表示し、選択プロンプト(変数PS3の内容)を表示します。番号を入力すると、対応する文字列が変数に代入されdo〜doneのブロックが実行されます。入力された番号はREPLY変数に格納されます。

      例)
      $ cat foo
      #
      PS3="SELECT->"
      select x in りんご ばなな おれんじ おわり
      do
        if [ $REPLY = "4" ]
        then
          break;
        fi
        echo $REPLY=$x
      done

      $ foo
      1) りんご
      2) ばなな
      3) おれんじ
      4) おわり
      SELECT->1
      1=りんご
      SELECT->4
       
      多分岐
      case 変数 in
       参照文字列)
        コマンド
           ;;
         esac

      文字列が参照文字列と一致するブロックのコマンドを実行します。参照文字列にはワイルドカードが使用できます。

      例)
      $ cat foo
      #
      case $1 in
        A*)
         echo 最初の文字はAです。
         ;;
        *C)
         echo 最後がCです。
         ;;
        XYZ)
         echo XYZです。
         ;;
        *)
         echo その他です。
         ;;
      esac

      $ foo ABC
      最初の文字はAです。
      $ foo BC
      最後がCです。
      $ foo BCD
      その他です。
      $ foo XYZ
      XYZです。
      switch (文字列)
       case 参照文字列:
        コマンド
        [breaksw]
       ・・・
       default:
        コマンド
      endsw

      文字列が参照文字列と一致するブロックのコマンドを実行します。参照文字列にはワイルドカードが使用できます。

      % cat foo
      #
      switch ($1)
        case A*:
         echo 最初の文字はAです。
        case *C:
         echo 最後がCです。
         breaksw
        case XYZ:
         echo XYZです。bが含まれます。
         breaksw
        default:
         echo その他
      endsw

      % foo ABC
      最初の文字はAです。
      最後がCです。
      % foo BC
      最後がCです。
      % foo BCD
      その他
      % foo XYZ
      XYZです。

    6. その他のコマンド

      入力

      read [変数名[?プロンプト文字列]] [変数名・・・]


      ユーザーからのキー入力を環境変数に読み込みます。
      変数名を省略した場合はREPLY変数に格納されます。

      例)
      $ read A?"Input?" B C D E
      Input?ab cd ef gh ij kl mn
      $ echo $A,$B,$C,$D,$E
      ab,cd,ef,gh,ij kl mn
      $ read X
      ab cd ef gh ij
      $ echo $X
      ab cd ef gh ij
      $ read
      ABCDEFG
      $ echo $REPLY
      ABCDEFG


      read -p [変数名・・・]

      -pオプションは、入力をパイプから読み込みます。Kシェルでは、パイプからの入力を変数へ読み込む事ができます。

      $ cat sample.ksh
      #!/usr/bin/ksh
      ls |&←lsの出力をパイプ連結して、このあとのスクリプトで受ける。
      while true
      do
        read -p x   #パイプからの読み込み
        if [ $? -ne 0 ] ; then exit ; fi ←$?はreadの終了ステータス。
        echo FILE:$x
      done

      $ ls
      sample.ksh test.txt
      $ sample.ksh
      FILE:sample.ksh
      FILE:test.txt

      set 変数名=$<

      ユーザーからのキー入力を変数に設定します。

      例)
      % cat sample.csh
      #
      echo -n "Input->"
      set x=$<
      echo "Input Data="$x

      % sample.csh
      Input->Test Data
      Input Data=Test Data
      画面出力
      echo [テキスト・・・]

      テキストを標準出力に出力します。
      テキスト出力後自動的に改行文字が追加されます。テキスト内では、次の特殊文字を使用できます。
      バックスペース \b
      行末に付けることで復帰改行を抑止します。 \c
      改ページ \f
      復帰 \n
      改行 \r
      タブ \t
      垂直タブ \v
      \記号 \\
      8進数nnnの文字コード \Onnn
      echo [-n] [テキスト・・・]

      テキストを標準出力に出力します。
      -nオプションを付けると、テキスト出力後の改行文字が追加されません。Kシェルのような特殊文字は使用できません。
      echo以外に、外部コマンドでprintfがあります。
      終了
      exit [n]

      シェルをnで指定した状態で終了させます。nを省略すると最後に実行されたコマンドの終了状態がシェルの終了状態になります(Kシェルにはexitと同等のreturn [n]もあります。)。

  7. シェル関数

    functions 関数名 {
     コマンド
     [return]
     ・・・
    }

    シェル関数は、Kシェルだけの機能です。
    シェル関数は、メモリ内に定義されたシェルスクリプトです。通常のシェルスクリプトと同様に引数や変数を参照でき、動作が高速です。retrurnステートメントで関数を脱出できます。
    関数は、aliasと同様に現シェルの環境で動作します(環境変数やカレントディレクトリの変更が現環境に影響します。)。

    $ function ll {<
    >ls -l $1 | nl
    >}

    ■定義済みの関数の表示

    functions

    functionsはtypeset -fのaliasです。

  8. 動作環境の設定

    シェルの動作環境の設定(ユーザーの作業環境の設定)は、通常ホームディレクトリのドットファイルで行います。ドットファイルとは、先頭が.で始まるファイルの事です。ドットファイルは、システム的に特別なファイルではありませんが、lsではオプションを付けないと表示されませんし、rm *とやっても削除されません(ファイル名を直接指定すれば削除できます。)。lsでは、aオプションを付けると表示されます。

    1. Kシェル

      Kシェルでは、ログインすると、/etc/profile,ホームディレクトリの.profile,環境変数ENVが設定されていれば、環境変数ENVに設定されたファイルを読み込んで処理します。
      /etc/profileは、Kシェルを使うユーザー全員に作用しますが、.profileは、そのディレクトリをホームディレクトリとしている人だけに作用します。

    2. Cシェル

      Cシェルでは、ホームディレクトリにある3つのファイルで環境設定を行います。

      ファイル 起動時期 備考
      .login ログイン ログイン後の子シェル起動時には実行されないため、ログイン時のメッセージや端末属性の設定、環境変数の設定をおこないます。
      .logout ログアウト ログアウトする時に処理したい処理を記述します。
      .cshrc Cシェル起動時 プロンプトの設定、別名コマンドの設定、履歴機能の設定などを行います。

  9. 特殊変数

    いままでにもいくつかは、出てきていますが、シェルの設定を変えたり、シェルが自動的に設定する変数についてまとめておきます。

    1. Kシェル

      数字 シェルスクリプトでの引数 $1,$2,$3・・・・
      # 引数の数
      ? 最後に実行されたコマンドの終了コード
      $ 現シェルのプロセス番号
      _ 直前のコマンドの最後の引数
      ! 最後に呼び出されたバックグラウンドプロセス番号
      ERRNO 失敗したシステムコールのエラー番号
      LINENO 実行中のスクリプトまたは関数内での現在の行番号
      OLDPWD cdコマンドで移動した時の移動前のディレクトリ
      OPTARG getoptsコマンドで処理された最後のオプション引数の値
      OPTIND getoptsコマンドで処理された最後のオプション引数のインデックス
      PPID 親のプロセス番号
      PWD 現在の作業ディレクトリ
      RANDOM この変数を参照するたびに、 0 から 32767 の乱数を発生します。
      REPLY 引数指定のないselect文read文で設定される入力の値
      SECONDS シェルが起動されてからの秒数
      CDPATH cdコマンドで相対パスが指定されたときに、検索するディレクトリ。環境変数PATHと同様の指定の仕方をします。
      COLUMNS この変数を設定すると、シェル編集モードとselectリストの編集ウィンドウの幅が、その値によって、定義されます。
      EDITOR コマンド行編集モードのエディタの指定。この値がemacs,gmacs,viのいずれかで、VISUAL変数が定義されていなければ有効。
      ENV この変数が設定されていると、シェル起動時に、そのファイルが実行される。ENVをexportしていなければ、ログオン時だけ。exportしていると、Kシェル起動時毎に実行されます。
      FCEDIT fcコマンドで使用するエディタの指定。
      FCEDIT=/usr/bin/vi
      HISTFILE コマンド履歴格納ファイルのパス(シェル起動時のみ有効)
      HISTSIZE コマンド履歴の数(シェル起動時のみ有効)。デフォルト128
      HOME ホームディレクトリ
      MAIL この変数にメールファイルの名前を登録し、MAILPATH変数を設定しない場合、メールが到着するとユーザーに通知されます。
      MAILCHECK MAILPATH変数またはMAIL変数で指定されたファイルが更新されたかどうかをシェルがチェックする間隔(秒)を設定。デフォルトは600秒。この時間が経過するとシェルは、次のプロンプトを出す前にチェックします。
      MAILPATH コロン(:)で区切ったメールファイルのリスト。
      PATH コロン(:)で区切ったディレクトリのリスト。コマンド検索パス。
      SVR4では、System V系(/usr/bin)とBSD系(/usr/ucb)コマンドの両方があるので、パスの設定で、コマンドセットを使い分けられます。
      PATH=.:$HOME/bin:/usr/bin:/usr/ucb
      PS1 1次プロンプト。デフォルト$
      PS2 2次プロンプト(コマンドが複数行のときなどに2行目以降に出るプロンプト)。デフォルト>
      PS3 selectで出るプロンプト。デフォルトは、#?
      SHELL シェルのパス名
      TMOUT 値が0より大きい値を設定すると、PS1プロンプト発行後、指定された秒数以内にコマンドが入力されないばあい、シェルは終了します。
      VISUAL emacs,gemacs,viのいずれかが設定されている場合。コマンド行編集モードが有効になります。

    2. Cシェル

      数字 argv[数字]と同じ。
      argv 引数リスト。argv[1],argv[2]・・・・
      cdpath cd,chdir,popdが総体パスで検索するディレクトリのリスト。ディレクトリの間はコロン:で区切ります。
      cwd カレントディレクトリ
      echo 設定すると(set echo)、aliasのコマンドを実行するときに、実行するコマンドを表示します。
      fignore ファイル名補完の時に無視する。例えば.oを指定。
      filec ファイル名補完を有効にします。
      hardpaths 設定すると、ディレクトリスタック内のパス名でシンボリックリンクの構成要素を含まないように展開されます。
      histcards 2文字の文字列を設定。1文字目は、コマンド履歴の!と置き換わり、2文字目は高速置換のための^と置き換わります。
      histry 履歴バッファの行数
      home ホームディレクトリ
      ignoreeof 端末からのEOF(Ctrl-D)を無視
      mail Cシェルがメールの有無をチェックするファイルのリスト。ファイル名の間は空白文字を入れる。最初のワードが数字の場合は、メールをチェックする間隔(秒)となります。デフォルトは5秒。
      nobeep ファイル名補完時のビープ音を抑制
      noclobber 既存のファイルを破壊しないように、出力先のリダイレクションを制限します。>は新規のファイルへのリダイレクションのみ、>>は既存のファイルへのリダイレクションのみが行えます。
      noglob ファイル名置換を禁止。
      nonomatich ワイルドカード展開時、パターンが一致するファイルがないと、エラーでなくファイル名置換パターンを返します。パターンが間違っているときはエラーを返します。(これは、よくわかりません。ごめんなさい。わかる人教えてください。)
      notify ジョブの終了をプロンプトを待たずに通知。
      path コマンドを検索するディレクトリのリスト。ディレクトリの間は空白文字(ブランク)で区切ります。pathは環境変数PATHと連動しています。
      prompt プロンプト。デフォルトのプロンプトは、特権ユーザーは#、一般ユーザーは%。
      savehist ユーザーがログアウトしたときに、~/.historyに保管される履歴リストの行数。savehistの行数が大きすぎるとCシェルの速度が遅くなります。
      shell シェルのパス名
      status 最後のコマンドの終了コード。
      time コマンド実行時間の報告
      verbose 履歴置換の後で各コマンドを表示します。