2010年06月18日 情報科学類 コンピュータリテラシ 筑波大学 システム情報工学研究科 コンピュータサイエンス専攻, 電子・情報工学系 新城 靖 <yas@is.tsukuba.ac.jp>
このページは、次の URL にあります。
http://www.coins.tsukuba.ac.jp/~yas/coins/literacy-2010/2010-06-18
あるいは、次のページから手繰っていくこともできます。
http://www.coins.tsukuba.ac.jp/~yas/
http://www.cs.tsukuba.ac.jp/~yas/
bash (Bourne-Again SHell) は、sh (Bourne Shell)の機能を強化したもの。 シェル・スクリプトを書く時には、多くのシステムで備わっている /bin/sh を 使うことも多い。(/bin/sh はあるが /bin/bash がないシステムもある。)
$ ls ~/Desktop | nkf -e
(デスクトップにあるファイルの一覧の表示。
漢字を含む名前のファイルも、nkf -e の働きで表示される。)
$
echo コマンド、history コマンド、あるいは、コピー&ペースト機能を用いて
端末から打ち込んだものを結果をファイルに保存する。以下の例では、echo コ
マンドを使ってファイルを作成している。
$ ls ~/Desktop | nkf -e
(^p で1行もどす。^a で、行頭に移動して 「echo '」と打ち、^e して
「' > ls-desktop」 と打つ)
$ echo 'ls ~/Desktop | nkf -e' > ls-desktop
$ cat ls-desktop
ls ~/Desktop | nkf -e
$ ls -l ls-desktop
-rw-r--r-- 1 yas prof 22 6 17 11:59 ls-desktop
$
不要な部分をエディタで削除すれば、シェル・スクリプトの完成である。この
例では不要な部分がないので、シェル・スクリプト ls-desktop は完成してい
る。完成したシェル・スクリプトを実行するには、次のようにbash コマンドの
引数としてファイル名を指定すればよい。
$ bash ls-desktop
(デスクトップの表示)
$
bash で動くものは、sh でも動くことが多い。
$ sh ls-desktop
(デスクトップの表示)
$
bash
」と打つのは煩わ
しいことがある。その場合は、次のようにする。
1行目にテキスト・エディタで #!/bin/bash
と書き加える。
$ emacs ls-desktop
(1行目に「#!/bin/bash
」と書き加える。)
$ cat ls-desktop
#!/bin/bash
ls ~/Desktop | nkf -e
$
chmod +x
で実行可能属性を付ける
$ ls -l ls-desktop
-rw-r--r-- 1 yas prof 34 6 17 12:09 ls-desktop
$ chmod +x ls-desktop
$ ls -l ls-desktop
-rwxr-xr-x 1 yas prof 34 6 17 12:09 ls-desktop
$
ファイル名を指定すると、実行することができる。ファイル名としては、明示
的に相対パス名であることを示すために先頭に「./
」を付けるか、ホー
ムディレクトリにあるこを示すために「~/
」を付ける(ホーム・ディレ
クトリにあることを仮定している)。
$ ./ls-desktop
(デスクトップの表示)
$ ~/ls-desktop
(デスクトップの表示)
$
~/bin
に置くと、他のコマンド(ls, cp,
emacs) 等と同じように実行することができる。
$ mkdir ~/bin
(注意: mkdir は、1度だけ実行すればよい。)
$ mv ls-desktop ~/bin
$ ls-desktop
(デスクトップの表示)
$
シェル・スクリプトを実行する時に、シェル・スクリプトに対して引数を与え ることができる。 The Unix Super Text 40.13.2 参照。
ls-desktop では、「デスクトップ」だけ表示できる。これはこれで便利である が、他の漢字を含む任意のディレクトリを表示したいという要求もある。たと えば、「書類」や「ダウンロード」も表示できるようにしたい。そこで、「引 数」としてディレクトリ名を含むようにする。シェル・スクリプトの名前を 「ls-e」 とする。
$ cd ~/bin
$ ls -l ls-desktop
-rwxr-xr-x 1 yas prof 34 6 17 12:09 ls-desktop
$ cp ls-desktop ls-e
$ ls -l ls-e
-rwxr-xr-x 1 yas prof 34 6 17 13:16 ls-e
$ emacs ls-e
(修正)
$ cat ls-e
#!/bin/bash
ls $* | nkf -e
$ ls -l ls-e
-rwxr-xr-x 1 yas prof 27 6 17 13:15 ls-e
(cp の時点で x ビットは立っているので chmod +x は不要。)
$ ls-e ~/Desktop
(デスクトップの内容)
$ ls-e ~/Downloads
(「ダウンロード」の内容)
$
この例では、ls-desktop の「~/Desktop」を「$*」に置き換えている。「$*」
は、コマンドに与えられた全ての引数ということを意味している。
$1,$2,...
で参照できる。
$*
では、全ての引数を参照できる。
shift
コマンドで引数をずらすことができる。
$#
で引数の数がわかる。
#
」を使ってコメントを書くことができる。bash は、
文字「#
」移行、行末まで無視する。
$ echo a b # c d
a b
$ # echo a b c
$
~/.bashrc
という名前のファイルにあるプログラムを自動的
に実行する。~/.bashrc
では、次のようなことを行う。
$ /usr/bin/emacs
$ /bin/ls
環境変数 PATH にディレクトリ名を登録しておくと、ディレクトリ名を省略す
ることができる。
例:
$ echo $PATH
(省略):/usr/bin:/bin:(省略)
$ emacs
$ ls
~/.bashrc
に保存する。
以下の例は、ssh でよくアクセスするホストをシェル変数に登録している。
$ cat ~/.bashrc
...
coins=coins.tsukuba.ac.jp
www=www.$coins
icho=icho.u.tsukuba.ac.jp
...
$
これを使うと、ssh が簡単になる。
$ ssh $www
$ ssh $icho
~/.bashrc
などを設定して、~/bin
を PATH環境変数に含まれ
るようにすることを奨める。自分で作成したプログラムやシェル・スクリプトを
~/bin
に置くと、ファイル名を指定しなくても
(「~/ファイル名
」や
「./ファイル
」打たなくて)、
~/bin
以下の短いファイル名で実行できるようになる。
coins では、標準で ~/bin
が PATH
に含まるように設定されて
いるので、各自設定する必要はない。
/bin/sh
) は、Bourne SHell と呼ばれる。対話的な利用では、csh
や bash を使う人でも、シェル・スクリプトを作成する時には、sh を使う人も多
い。
実際には、Unix オリジナルの sh ではなく、bash (GNU Bourne-Again SHell) という高機能のプログラムが広く使われている。bash が sh という名前で実行 された時に sh のごとく振舞う。多くの sh の機能は、bash ではそのまま利用 できる。
エイリアスとは一般に「別名」の意味。1つのものに2つ以上の名前をつける。
cd ~/public_html
」を簡単に実行するためのコマンド
「cd-web
」 を alias として定義する。
$ cd-web
-bash: cd-web: command not found
# 最初は cd-web というコマンドは見つからない
$ alias cd-web
-bash: alias: cd-web: not found
# 最初は cd-web という alias も見つからない
$ alias cd-web='cd ~/public_html'
# aliasの定義
$ alias cd-web
alias cd-web='cd ~/public_html'
# aliasの定義の確認
$ pwd
/home/prof/yas
# 最初はホーム・ディレクトリに居る
$ cd-web
# 定義したaliasの実行
$ pwd
/home/prof/yas/public_html
# ~/public_html に移動している。
$
~/.bashrc に alias の定義を追加したものを有効にするには、次のような方法 がある。
$ bash
$
$ . ~/.bashrc
$
$ cat ~/.bashrc
#
# coins standard ~/.bashrc
#
if [ -f /usr/local/lib/standard/bashrc ]; then
. /usr/local/lib/standard/bashrc
fi
# add your own code below
$
まず、端末で何かコマンドを実行しなさい。以下の例では、 /Applications/Calculator.app を実行している。
$ open /Applications/Calculator.app
(^p で1行もどす。^a で、行頭に移動して 「echo '」と打ち、^e して
「' > run-calc」 と打つ)
$ echo 'open /Applications/Calculator.app' > run-calc
$ cat run-calc
open /Applications/Calculator.app
$
bash の機能で、^p (Control+P) で1行戻して、echo でファイルに落とす。
echo には、実行したコマンドを
「'シングルクォート'」で括る(
'|'
) などして、エスケープして与えると安全である。
作成したファイルは、そのまま実行できる。
$ bash run-calc
いちいち bash と打たないでもいいようにするために、chmod
コマンド
で実行可能属性をつける。
$ ls -l run-calc
-rw-r--r-- 1 yas prof 34 6 16 15:08 run-calc
$ chmod +x run-calc
$ ls -l run-calc
-rwxr-xr-x 1 yas prof 34 6 16 15:08 run-calc
$ ./run-calc
$ ~/run-calc
$
エディタ(Emacs)で1行目に「#!/bin/bash」か「#!/bin/sh」を入れる。
#!/bin/bash
open /Applications/Calculator.app
完成したコマンドを ~/bin
に移動する。
$ mkdir ~/bin
(注意: mkdir は、1度だけ実行すればよい。)
$ mv run-calc ~/bin
$ run-calc
$
echo
コマンドではなく、history
コ
マンドを使う。
$ open /Applications/Firefox.app
$ open /Applications/Emacs.app
$ history
(ヒストリの表示して、何行必要か数える。
history コマンド自身の分、1行多く保存する。)
$ history |tail -3 > run-fe
history |tail -3 > run-fe
$ cat run-fe
512 open /Applications/Firefox.app
513 open /Applications/Emacs.app
514 history |tail -3 > run-fe
$ emacs run-fe
(不要な部分を削除する。1行目に #!/bin/bash と入れる。)
$ cat run-fe
#!/bin/sh
open /Applications/Firefox.app
open /Applications/Emacs.app
$ ls -l run-fe
-rw-r--r-- 1 yas prof 70 6 16 15:35 run-fe
$ chmod +x run-fe
$ ls -l run-fe
-rwxr-xr-x 1 yas prof 70 6 16 15:35 run-fe
$ ./run-fe
$ ~/run-fe
$ mkdir ~/bin
(注意: mkdir は、1度だけ実行すればよい。)
$ mv run-fe ~/bin
$ run-fe
$
$ cd /usr/bin
$ file * | grep shell
$
そのプログラムが、一般のプログラム(機械語)かシェル・スクリプトかは、 file コマンドを使うと調べることができる。
$ cd /usr/bin
$ ls -l apropos
-r-xr-xr-x 1 root wheel 1808 5 19 2009 apropos
$ file apropos
apropos: POSIX shell script text executable
$ head apropos
#!/bin/sh
#
# apropos -- search the whatis database for keywords.
# whatis -- idem, but match only commands (as whole words).
#
# Copyright (c) 1990, 1991, John W. Eaton.
# Copyright (c) 1994-1999, Andries E. Brouwer.
#
# You may distribute under the terms of the GNU General Public
# License as specified in the README file that comes with the man
$
if then else fi
for
while
case
exec
eval
exit
.
$((式))
で簡単な計算ができる。
この機能を確認しなさい。
The Unix Super Text 41.3.8項 参照。
$ cat add
#!/bin/bash
a=$1
b=$2
x=$(($a + $b))
echo $x
$ ./add 10 20
30
$
フィルタを利用したシェル・スクリプトを作成してみさない。
$ lldir ~
drwxr-xr-x 59 yas prof 12288 6 16 15:37 /home/prof/yas
$ lldir /
drwxrwxr-t 27 root admin 1326 4 22 15:43 /
$
$ date
2010年 6月17日 木曜日 16時57分54秒 JST
$ date-num
2010-06-17-16-57-55
$
$ date-cities
Tokyo
2010年 6月17日 木曜日 17時09分35秒 JST
New York
2010年 6月17日 木曜日 04時09分35秒 EDT
London
2010年 6月17日 木曜日 09時09分35秒 BST
$
ヒント: 都市の情報は、/usr/share/zoneinfo/ にある。
夏時間(daylight saving time/summer time)により、
経度の標準からずれていることもある。
$ l2 file.tex
ヒント: if を使う。 「&&」を使う方法もある。
$ lpshow file.tex
(画面には、file.pdf が Preview.app で表示される)
ヒント: 拡張子 .pdf を持つファイルを open コマンドで開くと、標準では
Preview.app が動作するが、他のプログラム(例えば Adobe Reader)にも変更で
きる。この課題でも他のプログラムを使ってもよい。
$ ls-c ~/syspro/file/
fd-print.c
file-copy.c
mmap-head.c
stdio-thru.c
utmp-print.c
wtmp-last10.c
ystat.c
ystat.h
ヒント:シェルの
ファイル名置換
で *.c や *.h といったファイル名のものだけを取り出す。
余裕があれば、-l などのオプションが付けられるようにしなさい。
$ ls-dot ~
.
..
.bashrc
.emacs
.login
$
ヒント
方法1:シェルの ファイル名置換 「.*」というパタンで探す。
方法2: ls に -a オプションを付けると、全てのファイルを表示し、 そのうち、先頭が「.」のものを抜き出す。 先頭が「.」のものを抜き出すには、 grep コマンドで次のパタンを検索する。
$ grep '^\.'
abc
.abc
.abc
aaa
.aaa
.aaa
^D
$
余裕があれば、-l などのオプションが付けられるようにしなさい。
$ lsd ~
Desktop/
Documents/
Downloads/
Library/
Mail/
Maildir/
Movies/
Music/
Pictures/
WinFiles/
bin/
public_html/
$
方法1: ls -F の結果を grep で必要なものだけを抜き出す。
方法2:
余裕があれば、-l などのオプションが付けられるようにしなさい。 余裕があれば、ls と同じように、ファイル名の順に並べ替えなさい。
$ ls-size ~yas/syspro/www
-rwxr-xr-x 1 yas prof 27056 Jun 12 11:54 cgi-printarg.cgi
-rwxr-xr-x 1 yas prof 18376 Jun 19 01:29 cgi-hello.cgi
-rw-r--r-- 1 yas prof 5287 Jun 12 11:54 cgi-printarg.c
-rw-r--r-- 1 yas prof 1579 Sep 26 2002 get.c
-rwxr-xr-x 1 yas prof 985 May 20 17:17 cgi-printarg-ruby.cgi
-rw-r--r-- 1 yas prof 486 Jun 11 21:20 cgi-hello.c
-rw-r--r-- 1 yas prof 297 Sep 22 2003 Makefile
drwxr-xr-x 5 yas prof 170 Jun 19 01:27 CVS
-rw-r--r-- 1 yas prof 54 Feb 14 2004 data
total 128
$
ヒント:ls -l の出力を sort コマンドでソートする。
ソートは、第5フィールドで行う。
$ wc-lines *.c
85 228 1836 proc-uid-print.c
75 187 1156 pipe-rw-dup.c
50 152 1141 vaddr-print.c
46 140 1071 proc-create.c
67 161 1014 pipe-rw-nodup.c
38 93 819 signal-int.c
50 98 802 setjmp-longjmp.c
32 90 561 run-n.c
27 66 535 home-print.c
20 50 424 cont-1.c
20 50 424 cont-0.c
25 60 419 t-system.c
20 40 384 exec-date.c
14 49 370 arg-print.c
15 44 355 env-print.c
12 32 305 cont-2.c
13 16 174 fork-hello.c
4 10 60 main-return.c
$
この課題では、合計(Total)は表示されなくてもよい。
ヒント:wc の出力を sort コマンドでソートする。for で1つずつ wc コマン ドを実行して、全体の結果を sort するか、引数 $* で wc した後、sort する。
$ ps aux
USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMAND
root 1 0.0 0.0 2456708 1356 ?? Ss 火08AM 1:26.40 /sbin/la
yas 3549 0.0 0.0 2435468 980 s000 Ss 3:40PM 0:00.01 -bash
yas 3548 0.0 0.0 2450900 748 ?? S 3:40PM 0:00.00 /usr/sbi
yas 3546 0.0 0.0 2456124 672 ?? Ss 3:40PM 0:00.01 /sbin/la
root 3544 0.0 0.1 2450900 4700 ?? S 3:40PM 0:00.27 /usr/sbi
root 3543 0.0 0.0 2446148 820 ?? Ss 3:40PM 0:00.00 /usr/lib
...
root 54 0.0 0.6 2468840 25220 ?? Ss 火08AM 0:43.01 /usr/lib
root 3556 0.0 0.0 2434788 428 s000 R+ 3:40PM 0:00.00 ps aux
$
そのうち、メモリのサイズ(RSS)が大きいプロセスを 10 個だけ表示するシェル・
スクリプトを作りなさい。
$ ps-rss-top10
USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMAND
root 318 0.0 3.0 215076 127388 ?? Ss 火08AM 1:12.05 /Library/
root 104 0.0 0.9 2567852 37332 ?? Ss 火08AM 0:41.42 /System/L
_windowserver 1007 0.0 0.6 2775984 25560 ?? Ss 火05PM 0:31.43 /Sys
root 54 0.0 0.6 2468840 25220 ?? Ss 火08AM 0:43.01 /usr/libe
root 1599 0.0 0.6 11156056 24040 ?? Ss 水02PM 0:09.13 /System/L
_mysql 218 0.0 0.5 2510832 18940 ?? S 火08AM 0:57.74 /opt/loca
_securityagent 1019 0.3 0.4 2757796 15396 ?? S 火05PM 7:51.89 /Sy
root 305 0.0 0.3 152008 14292 ?? S 火08AM 0:31.75 /Library/
root 1010 0.0 0.2 2727284 7956 ?? Ss 火05PM 0:03.56 /System/L
root 1050 0.0 0.2 2777952 7676 ?? Ss 火05PM 0:00.66 /System/L
$
ヒント:1行目は、そのまま表示する。RSS の順(第6フィールド)に sort して
head する。
余裕があれば、VSZ の順、CPU 時間の順に表示するスクリプトを作りなさい。
類似のことを実行するプログラムとして top がある。
$ diff-backup kadai10.txt
余裕があれば、比較しているファイルの名前を表示したり、ファイルごとに停
止する、引数を取る、diff に対するオプションを取る、などの工夫をしなさ
い。
$ diff-backup kadai10.txt kadai11.txt kadai12.txt
ヒント:for 文で、引数のファイルについて、"$file"~ のような名前のファイ
ルが存在するかを調べる。存在すれば、diff コマンドで表示する。
% mv-lower [A-Z]*
ヒント:ファイル名を echo して、tr で小文字にして、それを `` でシェル変数に入れる。元の名前から小文字 の名前に mv で変える。
余裕があれば、大文字と小文字を変換することで、ファイルが上書きされる時 には警告を出したり、ユーザに問い合わせたりするようにしなさい。
$ show-n-m 10 20 filename
余裕があれば、-n オプションを付けなさい。これは、ファイルに行番号を振 るものである。nl コマンドを使うとよい。(cat -n が使えるシステムもある。)
$ countdown 5
5
4
3
2
1
0
$
ヒント:sleep 1 で、1秒ごとに止める。
$ lv ~/.bashrc
$ lv /usr/local/lib/standard/bashrc
環境変数 PATHの値を観察しなさい。
$ echo $PATH
環境変数 PATH に含まれているディレクトリには、どのようなコマンドがある
かを調べなさい。例えば、/usr/local/bin を調べるには、次のようにする。
$ ls /usr/local3/coins/macosx/bin
path 以外にどのような
シェル変数と環境変数
が設定されているかを調べなさい。
ls -l
の代わりに
ll
というコマンドを使えるようにしなさい。
$ ls -l
total 80
-rw-r--r-- 1 yas prof 36224 6 16 16:24 index.html
-rw-r--r-- 1 yas prof 4459 6 16 16:24 screen-tab.png
$ ll
-bash: ll: command not found
# この時点ではコマンドは見つからない
$ alias ll='ls -l'
# alias による ll コマンドの定義
$ ll
total 80
-rw-r--r-- 1 yas prof 36224 6 16 16:24 index.html
-rw-r--r-- 1 yas prof 4459 6 16 16:24 screen-tab.png
$
$ alias
$ alias ll
名前='定義内容'
」
を引数として与える。例:
$ alias ll='ls -l'
$ unalias ll
~/.bashrc に alias の定義を追加しても、既に実行しているシェルには反映さ れない。実行しているシェルに反映させるには、「.」コマンドを用いる。
$ cat ~/.bashrc
#
# coins standard ~/.bashrc
#
if [ -f /usr/local/lib/standard/bashrc ]; then
. /usr/local/lib/standard/bashrc
fi
# add your own code below
alias ll='ls -l'
# ~/.bashrc に ll を追加した
$ ll
bash: ll: command not found
# 追加しただけでは、コマンドは見つからない
$ . ~/.bashrc
# 「.」コマンドで、~/.bashrc を読み込む
$ ll
(ls -l の表示)
# ll コマンドが有効になっている。
$
echo
でファイルに落すのではなく、alias
コマンドでエ
イリアスを定義する。
~/.bashrc
に追加する。
次の機能を確認しなさい。
jobs
コマンド
fg
コマンド
bg
コマンド
%
によるジョブの指定方法
stop
コマンド (%
による指定)
kill
コマンド (%
による指定)
(1) 練習問題(1909) から
練習問題(1926) まで
から1つ選んでシェル・スクリプトを作成しなさい。
作成したシェル・スクリプトを、ディレクトリ ~/bin
に起きなさい。
作成したシェル・スクリプトについて、次のことを書きなさい。
(2) 共通科目情報処理の 情報処理実習用手引き の次の章を読みなさい。
(3) 筑波大学における情報システム利用のガイドライン を読みなさい。 そして、疑問に思ったことを3項目以上示しなさい。たとえば、「3.10節 (a)の 端末をロックの意味が分からない」などと書きなさい。
(4) [加点] bash のエイリアス、または関数を定義しなさい。エイリアス は、~/.bashrc に保存しなさい。定義したエイリアス、または、関数について、 次のことを書きなさい。