東京工業大学大学院理工学研究科基礎物理学専攻中村研究室メンバー

ホームページおぼえがき > シェルスクリプト

シェルスクリプト

シェルスクリプトおぼえがき。Debian etch での使用が主。Bashについて書いてる?
(制作中。間違い有るかも。)

書き方のきまり

■ コメント

コメントは#の右側に書く。

# ここはコメント
echo "Hello, world!!" # ここもコメント 

シェルスクリプトにパスを通す

自作したシェルスクリプトは、相対パス/絶対パスで実行しなければいけないので面倒。
→パスを通すと楽。コマンド化できる。

■ 方法

  1. シェルスクリプトを置くディレクトリを作る。
  2. $ cd ~
    $ mkdir tools
    
  3. ディレクトリにパスを通す
  4. bashを使っておれば、シェルが起動したときに実行される~/.bashrcという設定ファイルがある。これに、以下の文を追加する。家のパソコンでは文末に追加した。

    if [ -d $HOME/tools ]
    then
        PATH=$PATH:$HOME/tools; export PATH
    fi
    
  5. 終わり
  6. これでどんなディレクトリにいても、toolsディレクトリに置いたシェルスクリプトのファイル名を打つだけで、実行ができる。まるで、コマンドのよう。むしろコマンドなのかな?

    注)シェルスクリプトのパーミッションを以下のように実行可能にしておく。さもなくば、動かない。

    $ cd ~/tools
    $ chmod u+x シェルスクリプト名
    

■ 補足

  • パスが通っているかは、端末で以下のように確認。
  • /home/username/toolsが入ってれば良い。
    $ echo $PATH
    /home/username/tools:/usr/local/bin:/usr/bin:/bin
    
  • bashrc
  • bashrcのrcはどうやら"Run Command"の略らしい

    リダイレクト、パイプ

    ■ >>, >, <

    これらは、リダイレクトを行うコマンドである。リダイレクトとは、シェルの入出力先を変更することであり、変更先は主にファイルとなる。

    ■ | , <<,

    この二つのコマンドは、入出力に関するコマンドである。>>, >, <と違い、ファイルから入力したり、ファイルへ出力したりしない。

    変数

    シェルスクリプトでは、変数を宣言なしに使える。変数は文字列のみを格納し、数値も文字列として解釈される?

    ■ 代入

    文字列を変数に代入し、その内容を表示する。

    $ para1="aa"
    $ para2='bb'
    $ para3=cc
    $ echo $para1 $para2  $para3
    aa bb cc
    $ echo ${para1} ${para2}  ${para3}   # こう書いても良い。むしろこっちのほうが応用が利く?
    aa bb cc
    $ echo "${para1}" '${para2}'         # ちなみに"と'の解釈の違い。
    aa ${para2}
    

    "や'を変数に代入し、その内容を表示する。

    $ para1="aa'aa"
    $ para2='bb"bb'
    $ echo $para1 $para2
    aa'aa bb"bb
    

    変数を解釈し、他の変数に代入する。

    $ para1="aa"
    $ para2="bb${para1}bb"
    $ para3='bb${para1}bb'
    $ para4=bb${para1}bb
    $ echo $para1 $para2 $para3 $para4
    aa bbaabb bb${para1}bb bbaabb
    

    エラー/いろんな書き方

    $ para1 = "aa"  # エラー。"="の左右にはスペースを入れてはいけない。
    bash: para: command not found
    
    $ para1="aa"
    $ para2="bb$para1bb" # 思い通りにいかない。(文字列"bbaabb"は代入されない。)
    aa bb
    
    $ para1="aa"
    $ para2="bb"   # 以下echoの出力に関するテスト。
    $ echo $para1$para2
    aabb
    $ echo "$para1""$para2"
    aabb
    $ echo $para1 $para2
    aa bb
    $ echo "$para1" "$para2"
    aa bb
    $ echo $para1         $para2
    aa bb
    $ echo "$para1"         "$para2"
    aa bb
    
    

    条件分岐

    ■ if文

    書式は以下のとおり。

    if [ 条件式1 ]
    then
      コマンド1a
      コマンド1b
    elif [ 条件式2 ]
      then
      コマンド2a
      コマンド2b
    else
      コマンド3a
      コマンド3b
    fi
    

    条件式1が真ならば、コマンド1a, コマンド1bのみが実行され、条件式2の真偽にかかわらず、他のコマンドは実行されない。条件式1が偽で、条件式2が真ならば、コマンド2a, コマンド2bのみが実行される。条件式1、条件式2がともに偽ならば、コマンド3a, コマンド3bのみが実行される。

    メモ1) elifや、elseの部分は書かなくてもよい?また、elifの部分はたくさん書いてもよいかも?

    メモ2) 条件式の返す値(?)は、0とか1じゃないかも?下記の例はともにtrueになる。

    $ if [ 1 ]
    >then
    >  echo "true"
    >else
    >  echo "false"
    >fi
    true
    
    $ if [ 0 ]
    >then
    >  echo "true"
    >else
    >  echo "false"
    >fi
    true
    

    ■ case文

    case 変数 in
       パターン1 ) コマンド1a ; コマンド1b ;;
       パターン2 ) コマンド2a ; コマンド2b ;;
       .....
       パターンn ) コマンドna ; コマンドnb ;;
               * ) コマンド*a ; コマンド*b ;;
    esac
    

    変数の値がパターン1に一致するときは、コマンド1a, コマンド1bのみが実行され、他のコマンドは実行されない。変数の値がパターン1に一致せず、かつパターン2に一致するときは、コマンド2a, コマンド2bのみが実行され、他のコマンドは実行されない。変数の値がパターン1〜パターンnに一致しないときに限り、コマンド*a, コマンド*bが実行される。パターンには正規表現も可。* )の行は書かなくてもよい。case文はif文を用いて同じことが出来そう。すなわち、if文があれば、case文は必要ないかも?

    また、以下のように書いても、エラーにならない。

    case 変数 in
       パターン1 )
                   コマンド1a
                   コマンド1b; コマンド1c;
                   コマンド1e; コマンド1f
                   コマンド1g
                   コマンド1h;   			   
       ;;
       パターン2 ) コマンド2a; コマンド2b 
       
                   コマンド2c
       ;;
    
    esac
    

    使用しているシェルの確認/変更

    ■ 現在使用しているシェルの確認

    以下のとおり。

    $ echo $SHELL
    

    ■ 現在のログインシェルの確認

    以下のとおり。

    $ finger username
    Login: username                             Name: username
    Directory: /home/username                   Shell: /bin/bash
    

    ちなみに現在のユーザーを調べるには、以下のようなコマンドを打つ。

    $ echo $USER
    

    ■ ログインシェルの変更

    以下のコマンドを打つ。ログイン時適用?

    $ chsh username
    Password: userのパスワードを入力
    kobaのログインシェルを変更中
    新しい値を入力してください, 標準設定値を利用するには リターンを押してください.
            ログイン・シェル [/bin/bash]: /bin/csh   ← cshに変更
    

    管理者の設定により無理な場合があるらしい。

    シェルスクリプト中のcdコマンド

    例えば、シェルスクリプト中に以下のようにcdコマンドを書き、そのシェルスクリプトをホームディレクトリ以外で実行すると、cdは実行されずホームディレクトリに移動しないように見える。

    ファイル名: smp1.sh
    #!/bin/bash
    cd ~/
    
    

    これは、シェルスクリプトを実行したシェル(カレントシェル)が、子プロセスとしてもう一つシェル(サブシェル)を走らせ、そこでシェルスクリプトを実行するためである。すなわち、一度cdは実行されるものの、シェルスクリプトの実行が終われば、子プロセスが終了し、元のディレクトリに戻ってしまう。

    これは、以下のシェルスクリプトを実行すれば、確認できる。ただし、pwd(print working directory)はカレントディレクトリを表示するコマンド。

    ファイル名: smp2.sh
    #!/bin/bash
    pwd
    cd ~/
    pwd
    
    

    カレントシェルでシェルスクリプトを実行するには、ドットコマンド . を用いる。例えば、上記のシェルスクリプト(ファイル名: smp2.sh)を実行すると、実行結果は以下のようになる

    username@hostname:~/dir1/dir2/dir3$ . smp2.sh		# . smp2.sh は、. ./smp2.sh と書いてもよい。
    /home/username/dir1/dir2/dir3
    /home/username
    username@hostname:~$
    

    本おぼえがきの書体について

    書体意味
    AaBbCc123端末の表示する文字。またはコードなど。$ You have mail.
    AaBbCc123ユーザーが入力する文字。
    端末の表示する文字と区別する。
    $ su
    password:
    AaBbCc123コマンドの引数やコードの可変部分。
    実際の名前や値と置き換える。
    $ rm filename

    参考文献・webページ


    ページ制作履歴
    2007/10/13 制作開始
    2007/10/14 アップ
    2007/11/20 シェルの確認、cdコマンド関係追加
    2007/12/25 条件分岐追加