c s h プログラミングの応用 0. 目次 1. 課題 課題 1 : 与えられたパス名からディレクトリ名とファイル名を分離し出力せよ 課題 2 : オプション (-in) の後に続く文字列とオプション (-out) の後に続く文字列をそれぞれまとめる オプションの指定がなく文字列から始まるとき -in を仮定する 課題 3 : 複数のファイルから与えられたパターンとマッチする文字列を含む行を取り出せ ただし パターンは ' で囲むこと 課題 4 : ファイルをコピーせよ 課題 5 : 標準入力からの入力をファイルに保存せよ 課題 6 : あるディレクトリの直下にあるファイルをすべて表示せよ ディレクトリが指定されない場合 現ディレクトリとする 課題 7 : あるディレクトリ以下の木構造をスタックを使って表示せよ 課題 8 : コマンドを再帰的に呼び出すことができる 再帰動作の確認をせよ 課題 9 : 指定されたディレクトリ以下の木構造を表示 ( 再帰呼び出しによる ) せよ 課題 1 0 : 指定されたディレクトリ以下の木構造を表示 ( 再帰呼び出しによる ) し 通常のファイルの場合 最初の 20 行を表示せよ また 不要なファイルは削除できること - 1 -
1. 課題 課題 1 : 与えられたパス名からディレクトリ名とファイル名を分離し出力せよ 利用法 : % csh111 パス名 ( ヒント ) 文字列の分離 オペレータ 機能 :r 文字列中の最右端にある. 以前を抽出 :e 文字列中の最右端にある. 以後を抽出 :h 文字列中の最右端にある / 以前を抽出 :t 文字列中の最右端にある / 以後を抽出 シェルプログラム (csh111) 2 # << csh111 >> 3 # 引数に対する処理 4 if( $#argv == 0 ) then 5 echo " 利用法 : % csh111 パス名 " 8 set temp = $1 9 while( $temp!= "" ) 10 # temp1 にパス名中の最右端 / 以前を抽出 11 set temp1 = $temp:h 12 if( $temp1 == $temp ) then 13 # パス名中に / がないとして終了 14 echo $temp 15 break 16 endif 17 # パス名中の最右端 / 以降を抽出し表示 18 echo $temp:t 19 set temp = $temp1 20 end % csh csh111 /A/B/a.c a.c B A % csh csh111 a.c a.c % csh csh111 利用法 : % csh111 パス名 - 2 -
課題 2 : オプション (-in) の後に続く文字列とオプション (-out) の後に続く文字列をそれぞれまとめる オプションの指定がなく文字列から始まるとき -in を仮定する 利用法 : % csh221 -in aaa -out bbb -in ccc シェルプログラム (csh211) 2 # << csh211 >> 3 # 引数に対する処理 4 if( $#argv == 0 ) then 5 echo " 利用法 : % csh211 -in 文字列 -out 文字列 " 8 set instring # オプション ( -out) の文字列 9 set outstring # オプション ( -in) の文字列 10 set ind = "-in" # オプションの状態を示す 11 while( $#argv > 0 ) 12 # temp1にパス名中の最右端 / 以前を抽出 13 set x = $argv[1] 14 shift argv 15 # オプション ( -in) の処理 16 # "$x" から " を取るとエラーになる 17 if( "$x" == "-in" ) then 18 set ind = $x 19 continue 20 endif 21 # オプション ( -out) の処理 22 if( "$x" == "-out" ) then 23 set ind = $x 24 continue 25 endif 26 # 文字列の処理 27 if( "$ind" == "-in" ) then 28 set instring = ( $instring $x ) 29 else 30 set outstring = ( $outstring $x ) 31 endif 32 end 33 echo " オプション ( -in): $instring" 34 echo " オプション ( -out): $outstring" % csh csh211 -in aaa -out bbb オプション ( -in): aaa オプション ( -out): bbb % csh csh211 aaa bbb -out ccc オプション ( -in): aaa bbb オプション ( -out): ccc % csh csh211 -out aaa bbb -in ccc オプション ( -in): ccc オプション ( -out): aaa bbb % csh csh211 利用法 : % csh211 -in 文字列 -out 文字列 - 3 -
課題 3 : 複数のファイルから与えられたパターンとマッチする文字列を含む行を取り出せ ただし パターンは ' で囲むこと 利用法 : % csh311 パターンファイル名ファイル名 シェルプログラム (csh311) 2 # << csh311 >> 3 # 引数に対する処理 4 if( $#argv <= 1 ) then 5 echo " 利用法 : % csh311 パターンファイル名ファイル名 " 8 # パターンを取り出す 9 set pat = $1 10 shift argv 11 # 引数に指定されたすべてのファイルに付いて繰り返す 12 while( $#argv > 0 ) 13 if(! -e $1 ) then 14 echo " ファイル [$1] は存在しません " 15 goto fin 16 endif 17 # ファイル名の出力 18 echo "[$1]" 19 # 見つかった行に行番号を付加するオプション ( -n) 20 grep -n "$pat" "$1" 21 fin: 22 shift argv 23 end % cat aaa line1 line2 line3 % cat bbb LINE1 LINE2 LINE3 LINE4 LINE5 % csh csh311 '3' aaa bbb [aaa] 3:line3 [bbb] 3:LINE3 isemba@hcs[14]:csh csh311 利用法 : % csh311 パターンファイル名ファイル名 - 4 -
課題 4 : ファイルをコピーせよ 利用法 : % csh411 コピー元ファイル名コピー先ファイル名 ( ヒント ) コピー元ファイルの存在 コピー先ファイルの存在を確認してから適切な処理をすること ファイルの状態を調べる方法 書き方 機能 -d ファイル名 ディレクトリファイルの場合に真 -e ファイル名 ファイルが存在している場合に真 -f ファイル名 通常のファイルの場合に真 -r ファイル名 ファイルが読み出し可の場合に真 -w ファイル名 ファイルが書込み可の場合に真 -x ファイル名 実行ファイルの場合に真 -z ファイル名 ファイルが存在して空の場合に真 シェルプログラム (csh411) 2 # << csh411 >> 3 # 引数に対する処理 4 if( $#argv == 0 ) then 5 echo " 利用法 : % csh411 コピー元ファイル名 コピー先ファイル名 " 8 # コピー元ファイルが存在しない場合の処理 9 if(! -e $1 ) then 10 echo " コピー元ファイルが存在しません " 11 exit(0) 12 endif 13 # コピー先ファイルが存在する場合の処理 14 if( -e $2 ) then 15 echo " コピー先ファイルが存在します " 1 1 18 # awkコマンドによるコピー 19 awk '{print $0}' $1 > $2 % cat aaa line1 line2 line3 % csh csh411 ccc ddd コピー元ファイルが存在しません % csh csh411 aaa bbb コピー先ファイルが存在します % csh csh411 aaa ccc % cat ccc line1 line2 line3-5 -
課題 5 : 標準入力からの入力をファイルに保存せよ 利用法 : % csh511 > コピー先ファイル名 シェルプログラム (csh511) 2 # << csh511 >> 3 # 引数に対する処理 4 if( $#argv!= 0 ) then 5 echo " 利用法 : % csh511 > コピー先ファイル名 " 8 while( 1 ) 9 # 標準入力からの入力 10 set input = $< 11 # ファイル中に改行コードのみの行 ( 見かけは空行となる ) があると 12 # ファイルの最後と解釈され終了する 13 if( $input == "" ) then 14 break 15 endif 16 # 標準出力へ出力 17 echo "$input" 18 end % csh csh511 > xxx 111 222 333 enter キーを押す % cat xxx 111 222 333-6 -
課題 6 : あるディレクトリの直下にあるファイルをすべて表示せよ ディレクトリが指定されない場合 現ディレクトリとする 利用法 : % csh611 ディレクトリ名 シェルプログラム (csh611) 2 # << csh611 >> 3 # 引数に対する処理 4 if( $#argv > 1 ) then 5 echo " 利用法 : % csh611 ディレクトリ名 " 8 # ディレクトリの確認 9 if( $1 == "" ) then 10 set dir = `pwd` 11 else 12 set dir = $1 13 if(! -d $dir ) then 14 echo "$dir はディレクトリではありません " 15 exit(1) 16 endif 1 18 # すべてのファイルを表示 19 foreach file ( `\ls $dir`) 20 echo $file 21 end % csh csh611 aaa bbb ccc csh111 csh211 csh311 csh411 csh511 csh611 xxx - 7 -
課題 7 : あるディレクトリ以下の木構造をスタックを使って表示せよ 利用法 : % csh711 ディレクトリ名 シェルプログラム (csh711) 2 # << csh711 >> 3 # 引数に対する処理 4 if( $#argv > 1 ) then 5 echo " 利用法 : % csh711 ディレクトリ名 " 8 # ディレクトリの確認 9 if( $1 == "" ) then 10 set dir = `pwd` 11 else 12 set dir = $1 13 if(! -d $dir ) then 14 echo "$dirはディレクトリではありません " 15 exit(1) 16 endif 1 18 # スタックの準備 19 set stack = $dir 20 # 木構造を探索する 21 while( $#stack > 0 ) 22 # スタックから要素を 1 つ取り出す 23 set x = $stack[1] 24 shift stack 25 # ディレクトリの場合 26 if( -d $x ) then 27 echo $x/ 28 foreach file ( `\ls $x` ) 29 # ディレクトリ内のファイルが連続するように stackに代入 30 set stack = ($x/$file $stack) 31 end 32 # 実行ファイルの場合 33 else if( -x $x ) then 34 echo $x\* 35 # 通常のファイルの場合 36 else if( -f $x ) then 37 echo $x 38 # その他のファイルの場合 39 else 40 echo $x ' 不明 ' 41 endif 42 end - 8 -
% csh csh711 DIRA DIRA/ DIRA/filea DIRA/DIRB/ DIRA/DIRB/fileb % ls -lr DIRA DIRA: 合計 8 drwxr-xr-x 2 isemba staff 4096 9 月 18 日 21:53 DIRB -rw-r--r-- 1 isemba staff 13 9 月 18 日 21:52 filea DIRA/DIRB: 合計 0 -rw-r--r-- 1 isemba staff 21 9 月 18 日 21:53 fileb - 9 -
課題 8 : コマンドを再帰的に呼び出すことができる 再帰動作の確認をせよ 利用法 : % csh811 5 シェルプログラム (csh811) 2 # << csh811 >> 3 if( $#argv!= 1 ) then 4 echo " 利用法 : % csh811 数値 " 5 exit(0) 6 endif 7 if( $1 == 0 ) then 8 exit(0) 9 else 10 echo "--->[$1]" 11 @ x = $1-1 12 csh811 $x 13 echo "<---[$1]" 14 endif % csh csh811 2 --->[2] csh811: アクセス権がありません <---[2] % chmod 755 csh811 % csh811 1 --->[1] <---[1] % csh811 2 --->[2] --->[1] <---[1] <---[2] % csh811 3 --->[3] --->[2] --->[1] <---[1] <---[2] <---[3] - 10 -
シェルプログラム (csh821) 途中結果を保存する方法 1 # << csh821 >> 2 if( $1 == 0 ) then 3 echo "sum=$2" 4 exit(0) 5 else 6 echo "--->[$1]" 7 if( $2 == "" ) then 8 @ sum = 1 9 else 10 @ sum = $2 + 1 11 endif 12 @ x = $1-1 13 csh821 $x $sum 14 echo "<---[$1]" 15 endif % chmod 755 csh821 % csh821 0 sum= % csh821 1 --->[1] sum=1 <---[1] % csh821 2 --->[2] --->[1] sum=2 <---[1] <---[2] % csh821 3 --->[3] --->[2] --->[1] sum=3 <---[1] <---[2] <---[3] - 11 -
課題 9 : 指定されたディレクトリ以下の木構造を表示 ( 再帰呼び出しによる ) せよ 利用法 : % csh911 ディレクトリ名 シェルプログラム (csh911) 2 # << csh911 >> 3 # 引数に対する処理 4 if( $#argv > 1 ) then 5 echo " 利用法 : % csh911 ディレクトリ名 " 8 # ディレクトリの確認 9 if( $1 == "" ) then 10 set dir = `pwd` 11 else 12 set dir = $1 13 if(! -d $dir ) then 14 echo "$dirはディレクトリではありません " 15 exit(1) 16 endif 1 18 # 木構造を探索する 19 foreach i (`/bin/ls $dir`) 20 # ディレクトリの場合 21 if( -d $dir/$i ) then 22 echo $dir/$i/ 23 csh911 $dir/$i 24 # 実行ファイルの場合 25 else if( -x $dir/$i ) then 26 echo "$dir/$i 実行ファイル " 27 # 通常のファイルの場合 28 else if( -f $dir/$i ) then 29 echo `file $dir/$i` 30 # その他のファイルの場合 31 else 32 echo "$dir/$i" 33 endif 34 end - 12 -
% chmod 755 csh911 % csh911 DIRA DIRA/DIRB/ DIRA/DIRB/fileb: ASCII テキスト DIRA/filea: ASCII テキスト % ls -lr DIRA DIRA: 合計 8 drwxr-xr-x 2 isemba staff 4096 9 月 18 日 21:53 DIRB -rw-r--r-- 1 isemba staff 13 9 月 18 日 21:52 filea DIRA/DIRB: 合計 0 -rw-r--r-- 1 isemba staff 21 9 月 18 日 21:53 fileb - 13 -
課題 1 0 : 指定されたディレクトリ以下の木構造を表示 ( 再帰呼び出しによる ) し 通常のファイルの場合 最初の 20 行を表示せよ また 不要なファイルは削除できること 利用法 : % csh1011 ディレクトリ名 2 # << csh1011 >> 3 # 引数に対する処理 4 if( $#argv > 1 ) then 5 echo " 利用法 : % csh1011 ディレクトリ名 " 8 # ディレクトリの確認 9 if( $1 == "" ) then 10 set dir = `pwd` 11 else 12 set dir = $1 13 if(! -d $dir ) then 14 echo "$dirはディレクトリではありません " 15 exit(1) 16 endif 1 18 # 木構造を探索する 19 foreach i (`/bin/ls $dir`) 20 # ディレクトリの場合 21 if( -d $dir/$i ) then 22 echo $dir/$i/ 23 csh1011 $dir/$i 24 continue 25 endif 26 # 実行ファイルの場合 27 if( -x $dir/$i ) then 28 echo $dir/$i\* 29 continue 30 endif 31 # 通常のファイルの場合 32 if( -f $dir/$i ) then 33 echo "[$dir/$i]" 34 head -20 $dir/$i 35 repeat 40 echo -n "=" 36 echo " " 37 echo -n " 続けますか [y/n/del]: " 38 set in = $< 39 if( $in == "n" ) then 40 break; 41 endif 42 if( $in == "del" ) then 43 \rm -i $dir/$i 44 endif 45 continue 46 endif 47 # その他のファイルの場合 48 echo $i ' 不明 ' 49 end - 14 -
% chmod 755 csh1011 ディレクトリ (DIRA) 以下を表示 % ls -R DIRA DIRA: DIRB filea DIRA/DIRB: fileb csh1011 を実行 % csh1011 DIRA DIRA/DIRB/ [DIRA/DIRB/fileb] 111 222 333 444 555 ======================================== 続けますか [y/n/del]: y [DIRA/filea] aaa bbb ccc ======================================== 続けますか [y/n/del]: del rm: DIRA/DIRB/filec を消去しますか (yes/no)? yes ディレクトリ (DIRA) 以下を表示 % ls -R DIRA DIRA: DIRB DIRA/DIRB: fileb - 15 -