最終更新日 …
$Date: 2003-05-18 13:04:13+09 $
unix では短い単純なプログラムを上手に繋げて複雑な動作を素早く柔軟に行なう,
というのが基本姿勢の一つである.
そのための仕組みの一つが,標準入出力とその制御であるリダイレクション,パイプラインである.
これらの概念は unix cui 環境での作業では必須であるので,あって当たり前という空気のように思えるぐらいにまで,きちんと学んでおこう.
![]() |
基本的なプログラムは,定められた入出力先として
「標準入力」「標準出力」「標準エラー出力」を用いるのが普通である.
そして,この「標準入出力」が繋がる相手をユーザーが自由に制御できるのである. この制御が「リダイレクション」や「パイプライン」とよばれる技術であり, これを使いこなすことで,unix cui 環境の真髄に一歩近づくことができる. 詳細は以下に述べる. |
unix ではプログラムはチャネル,もしくは デスクリプタ(ファイル記述子) とよばれる出入り口ファイルを用いてデータの入出力を行なう. 機器や環境に依存しない汎用入出力を可能とする目的で, unix ではこのうちの最初の 3つ(0 〜 2番)のデスクリプタを特別なものとして決めている. これらが標準入出力とよばれるものであり,次のような性質を持っている.
これら標準入出力によるデータの入出力の相手はプログラム側からは決められず,
そのプログラムを起動したシェルが決める約束になっている.
# 何も指定しないと,通常は
キーボード → プログラム → ディスプレイ
と繋がっていることになる.
標準入出力先を何にするかはユーザーが簡単に変更できる.
これを上手に使えば,同じプログラムの出力をファイルへ出力したり,ディスプレイへ出力したり,
出力させなかったりと変更することを「プログラム側で全く考慮する事なく」
行なうことができる.
この「標準入出力先を変更すること」,すなわち標準入出力の制御を,(I/O)リダイレクションとよぶ.
unix ではこの機能によって,基本動作だけのプログラムを非常に広い対象に適用することができる.
これが「unix の cui 環境は使い込めば強力である」
といわれる一因となっている.
そこで,以下に「一つのプログラムに対する」具体的なリダイレクションの方法を示そう.
# 二つのプログラムの入出力を直接繋げてしまう「同時リダイレクション」は特別に「パイプライン」と呼ばれる.
詳しくは後述する.
文法がシェルによってわずかに異なるため,以下に sh 系と csh 系とにわけて示しておく.
# 阪大教育用計算機システムを使っている諸君は,たぶんに bash を使っているだろうから,
とりあえず sh 系の方だけをみておけばよいだろう.
多すぎて良く分からないという場合は,
赤字
で書かれている3ヶ所を理解して覚えるだけでも十分だろう.
sh 系 | csh 系 | 意味 | |
---|---|---|---|
入力の変更 |
< file
|
標準入力を file に変更.
|
|
<< endstr
|
標準入力を最初の endstr から次の endstr までの内容に変更.
"Here Document" 機能とよばれる. |
||
出力の変更 |
> file
|
標準出力を
file
に変更.
file
が存在しなければ作成され,既に存在するならば内容は(消去されて)上書きされてしまう.
csh 系および新しめの sh系で noclobber 変数をセットしてあるときは,既に file
が存在するならばエラーになる.
(大切なファイルに上書きして内容を失わないための機能) |
|
>| file
|
>! file
|
(noclobber 変数を無視して)
標準出力を
file
に変更.
noclobber 変数をセットしてあっても無視して強制的に上書きする. |
|
>> file
|
標準出力の出力を
file
の末尾に追加していく.
file
が存在しなければ作成される.
ただし,csh 系で noclobber 変数をセットしてあるときは, file
が存在しなければエラーになる.
|
||
>>! file
|
(noclobber 変数を無視して)
標準出力の出力を
file
の末尾に追加していく.
|
||
2> file
|
標準エラー出力を
file
に変更.
ファイルの存在, noclobber 変数との関係は上記同様. |
||
( コマンド > file1 ) >& file2
|
標準出力を
file1
に,
標準エラー出力を
file2
に各々変更.
(標準エラー出力だけを変更することはできない) ファイルの存在, noclobber 変数との関係は上記同様. |
||
> file 2>&1
|
>& file
|
標準出力と標準エラー出力の出力を両方とも
file
に変更.
ファイルの存在, noclobber 変数との関係は上記同様. |
|
>| file 2>&1
|
>&! file
|
(noclobber 変数を無視して)
標準出力と標準エラー出力の出力両方とも
file
に変更.
noclobber 変数をセットしてあっても無視して強制的に上書きする. |
|
>> file 2>&1
|
>>& file
|
標準出力と標準エラー出力の出力の両方を
file
の末尾に追加していく.
ファイルの存在, noclobber 変数との関係は上記同様. |
|
>>&! file
|
(noclobber 変数を無視して)
標準出力と標準エラー出力の出力両方とも
file
の末尾に追加していく.
|
リダイレクションの実例
例えば,
ls -lg
の結果をゆっくり調べたいとしよう.
画面に出力されるものを覚えておくのも手かも知れないが(^-^),
人間の記憶力には限界がある.
そこで,この出力結果をファイルにしておいて,じっくり眺めるのが良い.
それには,
ls -lg > sample-file
← ls コマンドの出力先を,sample-file というファイルにリダイレクトしている
とすれば,
sample-file
という名前のファイルに
ls -lg
の結果が収められる.
だから,例えば less コマンドを使って
> less sample-file 合計 9756 -rw-r--r-- 1 ot-026fd others 0 May 11 14:32 #.xemacs# -rw-r--r-- 1 ot-026fd others 36 May 11 14:34 #test.txt# drwx--s--x 23 ot-026fd others 2048 May 29 20:52 ./ drwxr-sr-x 43 root sys 1024 Apr 8 18:54 ../ -rw-r--r-- 1 ot-026fd others 0 May 11 08:47 .Change2tcsh -rw------- 1 ot-026fd others 505 May 28 16:14 .ICEauthority drwxr-sr-x 3 ot-026fd others 512 May 24 13:57 .Mathematica/ -rw-r--r-- 1 ot-026fd others 23158 Apr 15 22:56 .RealNetworks_RealMediaSDK_60 -rw-r--r-- 1 ot-026fd others 485 Apr 15 22:56 .RealNetworks_RealPlayer_60 -rw-r--r-- 1 ot-026fd others 92 Apr 15 22:56 .RealNetworks_RealShared_00 drwxr-sr-x 3 ot-026fd others 512 May 8 14:53 .Wnn6/ …略…
と中身をいつでも繰り返しゆっくり見ることができる.
さらに,ここにあるファイルをサイズ順にリストアップしてみたいな〜
と思ったとしよう.
すると,sort コマンド(中身を並べる)を使って,上の
sample-file
の中身の 5 番目の要素を大きい順に並べればよい.
この時は,入力と出力の両方をリダイレクションすれば便利だ.
だから以下のようにすればよい.
sort +4 -nr < sample-file > sample-file2
← sort コマンドの入力先を sample-file に,
出力先を sample-file2 に
リダイレクトしている
こうすれば,
sample-file2
に望みの結果が入っている.
実習
覚えておくと便利なリダイレクト先
/dev/null
上の表を見ても分かるように,リダイレクト先には通常はファイルを指定する.
この時,unix に存在する特別なファイル(デバイスファイルの一種)
/dev/null
が非常に便利に使えるので覚えておこう.
このファイルは「ブラックホールファイル」とでも言うべき次の性質を持っている.
よって,この性質を使って次のようなことができる.
cp /dev/null
ファイル名
touch
ファイル名
とするという方法がよく知られている.
> /dev/null 2 >&1
… sh 系の場合
>& /dev/null
… csh 系の場合
/dev/null
にしておく,という使い方もできる.
通常のリダイレクションは,一つのプログラムの標準入出力を自分で変更できる.
よって,リダイレクションを使えば,
[ファイルを媒介したプログラムの接続] Program A →(出力)→ ファイル →(入力)→ Program B
とすることで二つ以上のプログラムの入出力をファイルを媒介することで繋げることができ,
単純な機能の組み合わせで複雑なことができる.
しかし,毎回ダミーのファイルを介在させるのは無駄だし,間違えも起きるだろう.
そこで,
Program A の標準出力と Program B の標準入力を直接繋いでしまう方法が
unix には用意されている.
この同時リダイレクションとでもよぶべき方法は,
「パイプ」もしくは「パイプライン」と呼ばれ,次のように使う.
sh 系 | csh 系 | 意味 |
---|---|---|
Program A | Program B
|
Program A の標準出力を Program B の標準入力として渡す. | |
Program A 2>&1 | Program B
|
Program A |& Program B
|
Program A の標準出力と標準エラー出力を Program B の標準入力として渡す. |
(注) パイプは好きなだけ何段にも重ねることができる.
パイプの実例
例えば,
ps -axu
の結果を画面で見るとしよう.
そのままこのコマンドを実行すると,
大量のデータが出力されて画面上を流れていってしまうのは経験しているだろう.
こういうときは,less コマンドなどを用いて,一画面ずつ表示させるのが定石である.
それには
ps -axu | less
← ps コマンドの出力と
less コマンドの入力を直接 パイプで繋いでいる
とすればよい.
さらに,この結果をプロセスの名前順に並べ直すことによって見易くしたいな〜
と思ったとしよう.
すると,sort コマンドを使って,上の結果を並べ直せば良い.
それにはどうするかというと,パイプを二回使って,
ps -axu | sort +10 | less
← ps コマンドの出力と
sort コマンドの入力をパイプで繋ぎ,
さらに
sort コマンドの出力と
less コマンドの入力をパイプで繋いでいる(パイプを二段使っている)
とすれば,
sb8015th 8377 0.0 2.8 16700 3660 ? S 20:38 0:00 (dns helper) ot-026fd 8540 0.0 1.0 2384 1380 pts/0 S 21:04 0:00 -csh ot-026fd 8559 0.0 1.0 2384 1380 pts/0 R 21:19 0:00 -csh ot-026fd 8427 0.0 0.9 1900 1164 pts/0 S 20:48 0:00 -sh root 6796 0.4 12.2 41760 15644 ? S 19:03 0:35 /etc/X11/X -au root 1575 0.0 0.3 3180 444 ? S 14:21 0:00 /usr/bin/gdm - root 6797 0.0 1.2 3848 1652 ? S 19:03 0:00 /usr/bin/gdm - sb8015th 8267 0.0 3.0 6712 3848 ? S 20:38 0:00 /usr/bin/gnome sb8015th 8331 0.0 2.6 5304 3352 ? S 20:38 0:00 /usr/bin/sawfi sb8015th 8356 0.9 18.2 31716 23340 ? S 20:38 0:23 /usr/lib/netsc sb8015th 8305 0.0 2.4 5152 3128 ? S 20:38 0:00 /usr/local/bin …略…
などと,プロセス名順に並んだ結果が画面上で一画面ずつ見られるというものだ.
実習
リダイレクションやパイプを使うときに,
「ファイルにも取っておきたいけど,
画面で確認しながら作業できないので不安だ」
という思いがあると思う.
こういう時便利なのが
tee
コマンドで,
「標準入力を,標準出力とファイルにコピーする」機能を持つ.
どう使うかというと,例えば先の
ls -lg
の結果をファイルに収めるという例を考えてみよう.
この作業を先のやり方
ls -lg > file
でやると,
file
の中身を見るまでどうなっているかわからない.
しかし,tee コマンドを用いて,
ls -lg | tee sample-file
← ls コマンドの出力を
標準出力に出しながら,かつ,
sample-file というファイルにも出力する
とすると,結果は画面にも出力されつつ,
sample-file
という名前のファイルにも書込まれることになる.
慎重に作業を行ないたい,という時はこのコマンドを上手に使うのが良いだろう.
# 作業過程を記録しておく,という意味で似たようなものに
script
というコマンドがある.
どちらも使いこなせるようになって,適切に使い分けよう.
シェルには,コマンド置換という便利な機能がある.
これは,コマンド中の ` (バッククォート, 逆引用符) で囲んだ部分を
「先に実行してその結果で置き換える」
というものである.
これによって,コマンドの出力結果をあたかも文字列のように扱える.
簡単に言えば,通常ならば分けて行なう複数の操作を一行に書ける,ということである.
例えば,test-日付 という名前のファイルを作りたいな〜
と思ったとしよう(日付部分は月日の4桁とか).
日付を得るには,date コマンドが使える.
これはオプションを適当に指定すれば好きな形式で出力が得られる便利なコマンドだ.
例えば
date +%m%d
とすれば 4桁の数字の形で「月」「日」が得られる.
そこで,
touch test-`date +%m%d`
← date コマンドの出力結果が文字列となる
とする.
すると,コマンド置換によって,
赤字部分が先に実行されて,結果の4桁の数字に置き換えられる
ため,test-0529 などという(空っぽの)ファイルが作られることになる.
# これの応用で,「○○というプロセスを kill する簡単なコマンド」とかも作ることができる.
わざわざ ps -axu コマンドで調べて〜 とやらずに済むので楽だ.
詳しくはしばらく後の授業で行うが,詳しい学生は少し考えてみよう.
# (ヒント) grep コマンド(文字列を検索する)や awk を使うとよいだろう.
もうちょっと複雑な例も考えてみよう.
例えば,README という文字が頭についているファイルがいくつあるか調べたいな〜
と思ったとしよう.
すると,ls コマンドと wc コマンド(単語数を数える)を用いて
ls README* | wc -w
とすれば,該当するファイルが 3つあれば 3 という答えが得られる.
で,この作業を良く行なうので,このコマンドを alias などで簡単に入力できるようにしたいとしよう.
# alias についてはこの授業の後半部分で詳細を示す.
これは,
alias Rnum= 'ls README* | wc -w'
… sh 系の場合
alias Rnum 'ls README* | wc -w'
… csh 系の場合
と入力しておけばよい.
あとは
Rnum
と入力するだけで 3 とか 4 とか答えが得られる.
しかし,数字だけしか表示されないので味気ない.
そこで,echo コマンド(文字列を表示する)と組み合わせて,
alias Rnum 'echo "`ls README* | wc -w` Readme files exist."'
とする.
すると,
Rnum
と入力するたびに,
コマンド置換によって,
赤字部分が先に実行されて,結果の数字に置き換えられる
ため,
3 Readme files exist.
などという結果が表示されるようになる.
# こういう場合,単数形と複数形が異なるので,正しい英語にしたかったら面倒だ(^-^).
実習
tee
コマンドと先読み評価に関して,
上に示した実例と同じ作業をやってみる.
unix は自由度の高さ,というのも基本姿勢の一つである.
そのため,あらゆる場面で個人が自ら設定できる余地が非常に大きい.
これは裏を返せば,適切な設定を意識して行なわないといつまでたっても
unix を便利につかえるようにならない,ということでもある.
そこで,この講義では unix cui 環境を支えるシェルについてその設定を学び,
個人設定の技術的な側面について学ぶとともに,
unix における個人設定の重要さや幅の広さを理解するのが狙いである.
シェルおよびシェルから起動されるコマンドの動作の一部に影響を与える設定は, 以下のようなファイル中で行なわれる.
sh 系 | csh 系 |
---|---|
|
|
種類 | シェル変数 | 環境変数 | ||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
概要 |
シェルが固有に持つ変数.
シェル自身の動作にかかわる設定に用いられる.
名前は小文字で記述することが多い. |
シェルから起動されるコマンドの動作設定にかかわる変数.
環境変数をどう利用するかはコマンドが決めることである.
名前は大文字で記述することが多い. |
||||||||||||||||||||||||||||||||||
文法 |
|
|
||||||||||||||||||||||||||||||||||
(設定する)
代表的なもの |
|
|
設定ファイルの読み込み直し
シェルの設定ファイルを修正して,その効果をみるためにはどうしたらよいだろうか?
いったんログアウトしてまたログインする?
それは間違いではないが,あまりに効率が悪い.
そこで,設定ファイルを修正した後,すぐにその影響をみるために
「設定ファイルを読み込む」
コマンドを紹介しておく.
sh 系 | csh 系 |
---|---|
. ファイル名 … (ピリオド,空白, ファイル名)と並んでいる. 素の sh はこの方法しか使えない. | |
source ファイル名
… 現在,通常のシェルではこの方法が共通に使えるだろう.
|
実習
エイリアス(alias) とは,コマンドに「別名」をつける機能である.
素の sh にはこの機能はないが,bash や tcsh
などの近年の通常のシェルにはたいていついている機能であり,
簡単なわりに効果が大きいのでここで紹介しておこう.
エイリアスの具体的な効用は,いくつかある.
具体例も示しつつ解説しよう.
例はなるべく bash 形式で書いてある.
alias md='mkdir'
alias em='xemacs'
alias newfile='touch dummy-`date +%m%d`'
alias printfile 'a2ps \!* | lpr'
alias cp='cp -i'
alias mv='mv -i'
alias rm='rm -i'
alias man='jman'
alias ls='ls --color=auto -Fga'
alias newpath='PATH=hogehoge'
エイリアスを用いるための文法は次のようになる.
エイリアス単独で考えると,引数を用いることができる
csh 系のシェルの方が便利であるが,
sh 系のシェルの「関数」という仕組みを用いれば機能的にはほぼ同じといってよいだろう.
どちらにせよ,きちんとした機能を欲するのであれば
シェルスクリプトを組む手間とあまり変わらないし,
そうなれば特にどのシェルがよい悪いという区別はない.
# csh 系シェルでシェルスクリプトを組むべきではない,という流派もいるが(^-^).
シェルを使ってやや複雑なプログラムを組むこうした機能に関しては,
シェルスクリプトについて学ぶ講義で解説を行なう.
意味 | sh 系 | csh 系 | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
別名設定 |
alias 別名='コマンド'
ただし,引数は使えない. また,素の sh にはこの機能はない. |
alias 別名 'コマンド'
csh 系の場合,引数を次のようにして alias に含めることができる.
|
||||||||
解除 |
unalias 別名
|
|||||||||
表示 |
alias
|
|||||||||
関数設定 |
新関数名 () {
n 番目の引数を $n
として参照できる.
|
実習
swap a b
と入力すると,
b a
と表示されるような alias もしくは関数 swap
を実現してみろ,ということである.
上に出てきた TERM, TERMCAP といった環境変数やそれに類するものを設定する.
bash ならば .bash_profile ファイルで,
csh 系シェルならば .login ファイルで行なうのが良いだろう.
実際,通常ユーザが端末設定を行なう必要性はあまりないし,
トラブルことも多いので,
特に必要がなければ端末設定はしない方がよい.
# 昔は stty erase ^H などという設定をよく行なった.
しかし,現在のシェルではこうした設定はほとんど必要ないだろう.
ただし,キーバインディング(キー操作)を変えたいという場合は,
bash や tcsh のような新しめのシェルでは結構安全な方法が用意されている.
bash では .inputrc というファイル中にしかるべき設定を,
tcsh では bind コマンドを使って .tcshrc ファイル中でしかるべき設定を行なえばよい.
詳しくはオンラインマニュアルなどで調べること.
bash ならば .bash_profile で,
csh 系ならば .login で,ログイン時に起動されるコマンドを書いておく,
ということもできる.
これをうまく使って,例えば起動時に
などということができる.
この辺りは技術的なことよりも,運用の工夫に負うところが大である.
まあ,あまり凝らないほうがいいとは思うが(^-^).
実習
You use *** KB in this system.
この授業ではシェルのカスタマイズだけに絞って話を進めているが,
他にもエディタ自身の設定や,各種ソフトの設定はいくらでもある.
特に emacs の設定ではほとんど「なんでもできる」ほど自由度が高く,
真面目に取り組めば終りはない(^-^).
unix では,「ソフトは各人の好みに応じて設定して使うもの」
という思想が徹底しているので,積極的に自分に合う設定を探して設定を変更してみるのがよい.
環境カスタマイズの注意点
シェルの環境をカスタマイズしているときに,
「設定にかなり厳しいミスをしてしまい,ログインできなくなる」
という現象が起こることがある.
いったんこうなってしまうと,通常ユーザではどうしようもなくなることがあるため,
こうならないようにするよう注意が必要だ.
では具体的にはどうすればよいかというと,
カスタマイズが終わるまで絶対にログアウトしない kterm を一つは確保しておく
とか,
何か設定を変えたら別の端末(ソフト)からログインしてテストする
(= 現在の端末(ソフト)はログアウトしない)
などとすればよい.
以下に示された課題について
AppliedMath-Report-04
という題名をつけて e-mail にて教官宛にレポートとして提出せよ(教官のメールアドレスは授業中に口頭で伝える).
なお,レポートを e-mail の代わりに TeX で作成した書面にて提出してもよい.
課題内容