UNIXシェルスクリプト第10章 Part2

2つのディレクトリを比較するシェルスクリプト DirCmp

※指定した2つのディレクトリ下にあるファイル構成を比較し、

等しくないファイルをリスト表示する。以下の3パターンの表示を行う。

1番目のディレクトリ下にあって、2番目のディレクトリ下にはないファイル。

2番目のディレクトリ下にあって、1番目のディレクトリ下にはないファイル。

両方のディレクトリにはあっても、名前が同じだけで実体が異なるファイル。

 

-v 詳細表示オプション

  2つのディレクトリ下に同じ名称のファイルがあってその中身が異なっているとき、

  ファイルの何行目がどのように違っているのかを表示する。

 

DIR1_FILES=/tmp/files1.$$

$$にはスクリプトを実行した時のプロセスIDが入る。

そのため別の人が同時に複数動作させても利用する一時ファイルはそれごとに異なって混乱することはない。一時ファイルを利用する場合にはこのように$$変数を使うのはいいこと。

正常終了時も、途中終了時もこれらの一時ファイルを削除するようにしないといけない。

 

trp `rm -f /tmp/*.$$; exit 1`    1 2 3 15

このシェルスクリプトは実行中には1,2,3,15番のシグナルしか受け付けない。

つまりハングアップ、割り込み、クイット、終了。

これらのシグナルを受け取って処理が途中で中断された場合には、trapコマンドの引数が実行される。

 

find . \( -type f -o -type l \) -print | sort > $DIR1_FILES

カレントディレクトリ内で、ファイルタイプが f または l のファイルを探して、一覧表示する。ファイルタイプ l はシンボリックリンクを表す。

findコマンドがタイプ指定の部分を解釈しなくてはならないので、丸括弧を使い、\でエスケープしている。

sortコマンドでソートし、その結果を$DIR1_FILESに書き込む。

 

cat $DIR1_FILES $DIR2_FILES | sort | uniq -d > $COMMON_FILES

uniqコマンドは重複した行を1行にして表示する。

-dオプションは重複した行だけを表示する。

-uオプションは重複していない行だけを表示する。

なお、uniqコマンドは前後に並んだ行を比べるだけなので、先にsortコマンドで並べ替えておく必要がある。

 

if [ -s $TMP ] ; then

-sオプションはファイルが存在し、かつサイズが0でなければ真。

 

cmp -s $DIR1/$f $DIR2/$f

cmpコマンドは内容を比較する。

cmpコマンドの終了コードはファイルの内容が異なっていれば1になり、一致していれば0になる。

 

diff $DIR1/$f $DIR2/$f

diffコマンドでファイルの内容の違いを出力する。

UNIXシェルスクリプト第10章 Part1

ファイルの連結、表示を行うシェルスクリプト Cat

#!/bin/sh

シェルスクリプトの最初にはこの宣言が必要。

/bin/shで動作させるため。

 

if [ ! -r "$1" ] ; then

-rオプションはファイルが存在し、読み込み可能かどうかを判定する。

 

IFS=

while read LINE

readはIFS変数にセットされている空白、タブ、改行などを区切り文字として使う。

IFS変数にはデフォルトで空白、タブ、改行がセットされている。

IFS変数を空にすることで何も無視する文字はないとreadコマンドに教えることができる。

※実際には現在の値を別の変数に代入しておいて、後で元に戻すのが賢明。

 

while read LINE

do

 処理

done <"$1"

whileとreadを使ってリダイレクトしてファイルを読みこませると、

ファイルの終わりの行までを1行ずつ順番に処理させることができる。

 

shift

スクリプトの引数($1以降)の位置を1つずらす。

 

exit $ERROR

$ERRORの値が終了コードになる。

 

UNIXシェルスクリプト第9章 Part11

そのシステムを判断する名称を出力する関数 SystemType.sh

_HOSTNAME=`hostname | sed 's/\..*//'`

hostnameコマンドは、そのマシンのホスト名称を出力するものだが、

システムによってはドメイン名称も一緒に出すものがある。

/..* は最初のドット以後全部の文字列を表す。

 

第9章終了。

UNIXシェルスクリプト第9章 Part10

2つの文字列を比較する関数 StrCmp.sh

※2つの文字列を返し、3つの結果を返す関数。

前者と後者が等しければ 0

前者のほうが後者より小さければ -1

前者のほうが後者より大きければ 1 を標準出力に出力する。

 

_TMP=`{ echo "$1"; echo "$2"; } | sort | sed -n '1p'`

sedコマンドについて

-nオプションは処理後にすべての行を出力する代わりに、

テキストに対する処理pで出力を指示した行だけを表示する。

'1p'は1行目を表示するという意味。'2,4p'とすると2~4行目という意味。

 

 

UNIXシェルスクリプト第9章 Part9

応答要求メッセージを出力する関数 Prompt.sh

echo "${@-> }\c"

echo -n "${@-> }"

${@-> } という部分は $@ と ${variable:-value} , ${variable-value} の組み合わせ。

 

応答要求のスタイルを定型化した関数 Question.sh

if [ $# -lt 3 ] ; then

-lt は Less than ( < ) と同じ意味。

 

+x | -x ) set $ANSWER ;;

シェルはsetコマンドでオプションを切り替えられる。

-xオプションは「実行された内容を変数などを置換した状態で表示する」ためのもの。

つまりこれ以後、デバッグモードとしてシェルスクリプトが動作する。

+xを入力するとデバッグモードをオフにする。

 

!* ) eval `expr "$ANSWER" : "!\(.*\)'`

expr string : regex はマッチする文字列を返し、マッチしなかった場合は0を返す。

正規表現の一部が \( と )\ の間に囲まれる場合、その囲まれる文字列を返し、

マッチしなければヌル文字列を返す。

evalコマンドは変数や特殊文字の変換処理を行ってからコマンドとして実行する。

 

 

 

UNIXシェルスクリプト第9章 Part8

システムのタイプが正しいかどうかを判定する関数 IsSystemType.sh

unameコマンドを使ってシステムの名前を取得する。

uname -s       OSの名称

uname -m     ハードウェアのタイプ

uname -r       OSのリリース番号

 

if [ "$1" = "`uname -s`" ] ; then

    return 0

elif [ "$1" = "`uname -m`" ] ; then

    return 0

else

    case `uname -r` in

        "$1"* ) return 0 ;;

    esac

fi

OSの名称、ハードウェアのタイプ、OSのリリース番号の順にチェック。

リリース番号については厳密に一致しなくても正しいものとするための処理を行っている。

UNIXシェルスクリプト第9章 Part7

文字列が数値化どうかを判定する関数 IsNumeric.sh

※シェル変数に代入されている値は、たとえ数値であれ文字として扱われる。

しかしexprコマンドなどは。その文字列を数値として計算させることができる。

 

expr "$1" + 1 > /dev/null 2>&1

実行終了ステータスが欲しいので1を足して、結果やエラーを捨て去る。

exprコマンドの実行終了ステータスについて

 結果が0になるときの終了ステータスは1

 結果が0以外になるときの終了ステータスは0

 計算できなかった時の終了ステータスは2

 

if [ $? -ge 2 ] ; then

-ge は >= と同じ意味。

$? には直前のコマンドの実行終了コードが代入される。