04. 標準入出力, リダイレクション,パイプ / コマンド短縮,シェル設定

Photo by tian kuan on Unsplash



標準入出力, リダイレクション,パイプ

  短い単純なプログラムを組み合わせて複雑な動作を実現する

unix の重要なポリシーの一つ.
短い単純なプログラムのほうが作りやすく、性能もあげやすく、かつ、バグも少なくて、良いことずくめだという考え.


上に述べたのは Unix の重要なポリシーの一つで、 そのための仕組みの一つがこれから説明する標準入出力とその制御であるリダイレクション,パイプラインだ.

まず少し基本的な話をすると,unix では通常のプログラムは 「標準入力」「標準出力」「標準エラー出力」という特別な入出力先を持っている. そしてこの「標準入出力」が繋がる相手をユーザーがプログラムを起動するとき毎に自由に制御することができ, その方法が「リダイレクション」や「パイプライン」なのである.

aa

■ 標準入出力とその制御(リダイレクション,パイプ)の様子 ■



上図のように,プログラムの入出力先を''「プログラムの実行時にユーザが勝手に変えられる」''のである. 上で述べたポリシーにより ''「unix には単機能プログラムが たくさんある」'' ため,この機能と組み合わせると

まるでプログラミングをしたかのような,かなり自由なことがプログラミング不要で簡単に実現できる という「おいしい」状況が unix に出現する. これは本当に便利なので,ぜひ習得しよう.



標準入出力とは何か

unix ではプログラムはチャネル,もしくは デスクリプタ(ファイル記述子)とよばれる出入り口ファイルを用いてデータの入出力を行なう. 機器や環境に依存しない汎用入出力を可能とする目的で,unix ではこのうちの最初の 3つ(0 〜 2番)のデスクリプタを特別なものとして決めている. これらが標準入出力とよばれるものであり,次のような性質を持っている.

IO(Input/Output) 説明
標準入力(stdin) プログラムが汎用データ入力に使う.
指定していない場合,デフォルト値( 通常は端末キーボード )が用いられる.
標準出力(stdout) プログラムが汎用データ出力に使う.
指定していない場合,デフォルト値( 通常は端末ディスプレイ )が用いられる.
標準エラー出力(stderr) プログラムがエラーメッセージの汎用出力に使う.
指定していない場合,デフォルト値(通常は端末ディスプレイ)が用いられる.

これら標準入出力によるデータの入出力の相手はプログラムを起動したシェルが決める約束になっている.

注意: 何も指定しないとき(デフォルト)は,
(入力)キーボード → プログラム → (出力)ディスプレイ
と繋がっている.

注意: まあ普通は,標準エラー出力はあんまり気にしなくていい.とりあえず無視しておいてもまあ大丈夫だ.

リダイレクション

redirection

  標準入出力先を何にするかはユーザーが「利用時に」変更できる

これを上手に使えば,同じプログラムの出力をファイルへ出力したり,ディスプレイへ出力したり, 出力させなかったりと変更することを「プログラム側で全く考慮する事なく」 行なうことができる.

この「標準入出力先を変更すること」,すなわち標準入出力の制御を,(I/O)リダイレクションとよぶ.

そこで,以下に「一つのプログラムに対する」具体的なリダイレクションの方法を示そう.

注意: 二つのプログラムの入出力を直接繋げてしまう「同時リダイレクション」は特別に「パイプライン」と呼ばれる. 詳しくは後述する.

文法がシェルによってわずかに異なるため,以下に sh 系と csh 系とにわけて示しておく. (多くの学生は,たぶん bash を使っているだろうから,とりあえず sh 系の方だけをみておけばよいだろう)

多すぎて良く分からないという場合は, 赤字 で書かれている3ヶ所を理解して覚えるだけでも十分だろう.

リダイレクションのやり方… コマンド名の後ろに以下の「おまじない」をつければよい

標準入力を変更するには

sh/csh 共通 fish の場合 解説
<␣hoge 左に同じ 標準入力を hoge というファイルに変更する.
<<␣hoge
内容行1
内容行2

内容行最後
hoge
heredocs は shell に特別な規則を多く導入する「問題のある機能」なので fish では採用しない,とのこと. "heredocs"とよばれる syntactical sugar (糖衣構文). 標準入力を最初の ''hoge'' から次の ''hoge'' までの内容
に変更.
fish では代わりに

echo "\
内容行1
内容行2

内容行最後
" ¦ コマンド

などのように,パイプを使うことが推奨されている.
この際,最後のコマンドには "パイプからの入力を stdin として受け取れ" というオプションとしてオプション - を付ける必要があることがある.このオプションが必要かどうかはコマンドによって異なるのでコマンドのマニュアルを読むべし.

標準出力を変更するには

sh 系 csh 系 fish の場合 意味
>␣hoge

注: noclobber 変数をセットしておくと、消去・上書きを防げる.
同左. 同左.

ただし noclobber 変数を無視して動作する.
標準出力を hoge というファイルに変更する.
''hoge'' というファイルが存在しなければ作成する.
既に存在するならば内容は消去されて上書きされてしまう

(該当なし) (該当なし) >?␣hoge

注: noclobber 変数をセットしておくと、消去・上書きを防げる.
標準出力を hoge というファイルに変更する.
''hoge'' というファイルが存在しなければ作成する.
既に存在するならば内容は消去されて上書きされてしまう

>¦␣hoge >!␣hoge (該当なし) noclobber 変数を無視して 上の動作を行う.
>>␣hoge

注: noclobber 変数をセットしておくとエラーになり,書き込めない.
同左 同左.

ただし,noclobber 変数を無視して動作する.
標準出力の出力を hoge というファイルの末尾に追加していく.
''hoge'' が存在しなければ作成される.
(該当なし) (該当なし) >>?␣hoge

注: noclobber 変数をセットしておくと、消去・上書きを防げる.
標準出力の出力を hoge というファイルの末尾に追加していく.
''hoge'' が存在しなければ作成される.
(該当なし) >>!␣hoge (該当なし) noclobber 変数を無視して 上の動作を行う.

標準エラー出力を変更するには

sh 系 csh 系 fish の場合 意味
2>␣hoge (該当なし) sh系と同じ 標準エラー出力のみを ''hoge'' というファイルに変更.
noclobber 変数との関係は上記同様.
>␣hoge␣2>␣boke

注: それぞれ個別に > を >> に変えても良い(その場合は追記になる).
(''コマンド''␣>␣hoge )␣>&␣boke

注は左と同じ.
sh系と同じ 標準出力を ''hoge'' というファイルに, 標準エラー出力を ''boke''
というファイルに各々変更.
noclobber 変数との関係は上記同様.
&>␣hoge

もしくは

>␣hoge␣2>&1
>&␣hoge sh系と同じ 標準出力と標準エラー出力の出力を両方とも ''hoge'' というファイルに変更.
noclobber 変数との関係は上記同様.

なぜか sh/fish 系と csh系で使う文字が逆の並びなので要注意.
>¦␣hoge␣2>&1 >&!␣hoge (該当なし) noclobber 変数を無視して 標準出力/エラーの両方を ''hoge'' という
ファイルに出力.
&>>␣hoge

もしくは

>>␣hoge␣2>&1
>>&␣hoge sh系と同じ 標準出力/エラーの両方を ''hoge'' というファイルの末尾に追加.
noclobber 変数との関係は上記同様.
(該当なし) >>&!␣hoge (該当なし) noclobber 変数を無視して 標準出力/エラーの両方とも ''hoge'' という
ファイルの末尾に追加.
(該当なし) (該当なし) 2>? や 2>>? , &>? , &>>? 等は noclobbar 変数が設定されていれば動作しない.

リダイレクションの実例

例えば, ls␣-lg の結果をファイルに保存してゆっくり調べたいとしよう. こういうときは

1ls -lga > sample-file

↑ ls コマンドの出力先を,sample-file というファイルにリダイレクトしている

とすれば, ''sample-file'' という名前のファイルに ls␣-lg の結果が収められる.

そして、例えば less コマンドを使って less␣sample-file とすると

 1合計 108
 2drwxr-x--- 17 osboxes 4096  4月 23 18:11 .
 3drwxr-xr-x  4 root    4096  2月 26 15:12 ..
 4-rw-------  1 osboxes  395  4月 17 20:49 .bash_history
 5-rw-r--r--  1 osboxes  220  2月 26 15:12 .bash_logout
 6-rw-r--r--  1 osboxes 3771  2月 26 15:12 .bashrc
 7drwx------ 11 osboxes 4096  4月 14 18:37 .cache
 8drwx------ 15 osboxes 4096  4月 17 20:49 .config
 9drwx------  3 osboxes 4096  4月 17 20:30 .emacs.d
10drwx------  2 osboxes 4096  2月 26 15:24 .gnupg
11-rw-------  1 osboxes   20  4月 14 18:52 .lesshst
12drwx------  4 osboxes 4096  2月 26 15:20 .local
13-rw-r--r--  1 osboxes  306  4月 14 18:54 .pam_environment
14-rw-r--r--  1 osboxes  807  2月 26 15:12 .profile
15drwx------  2 osboxes 4096  2月 26 15:24 .ssh
16-rw-r--r--  1 osboxes    0  2月 26 15:22 .sudo_as_admin_successful
17-rw-r-----  1 osboxes    5  4月 23 18:09 .vboxclient-clipboard.pid
18-rw-r-----  1 osboxes    5  4月 23 18:10 .vboxclient-draganddrop.pid
19-rw-r-----  1 osboxes    5  4月 23 18:10 .vboxclient-seamless.pid
20-rw-r-----  1 osboxes    5  4月 23 18:10 .vboxclient-vmsvga-session-tty2.pid
21drwxr-xr-x  2 osboxes 4096  2月 26 15:20 Desktop
22drwxr-xr-x  2 osboxes 4096  2月 26 15:20 Documents
23drwxr-xr-x  2 osboxes 4096  2月 26 15:20 Downloads
24  …略…

というように,中身をいつでも繰り返しゆっくり見ることができる.

さらに,ここにあるファイルをサイズ順にリストアップしてみたいな〜 と思ったとしよう. すると,sort コマンド(中身を並べる)を使って, ''sample-file'' の中身の,''この場合は'' 4番目の要素を大きい順に並べればよい.
注意: ''ls␣-lga'' コマンドの結果の何番目にファイルサイズが表示されるかは環境に依存するので,自分で数えてから実行しよう.

このケースでは,入力と出力の両方をリダイレクションすれば便利だ. だから例えば以下のようにすればよい.

1sort -k 4 -nr < sample-file > sample-file2

↑ sort コマンドの入力先を sample-file に,出力先を sample-file2 にリダイレクトしている

こうすれば, ''sample-file2'' に望みの結果が入っている.

  実習

  • 上に示した実例と同じ作業をやってみる.
  • さらに,同様の方法で, 二つのディレクトリの中でサイズの大きな方から順に5つのファイルをリストアップするにはどうしたらよいか考えよ. そして実際に試してみよ.

覚えておくと便利なリダイレクト先 /dev/null
ファイルとしては空っぽの "ブラックホール" と思えば良い.

上の表を見ても分かるように,リダイレクト先には通常はファイルを指定する. この時,unix に存在する特別なファイル ''/dev/null'' が非常に便利に使えるので覚えておこう. このファイルは「ブラックホールファイル」とでも言うべき次の性質を持っている.

  • 標準入力先に指定すると,「何も出てこない」
  • 標準出力先に指定すると,「全て飲み込んで,何も変化しない」

よって,この性質を使って次のようなことができる.

空っぽの新しいファイルを作れる.

1cp /dev/null  ファイル名

とすると,新しく空っぽのファイルが作られる. 新しくファイルを作成する方法としては,他に

1touch ファイル名

とするという方法もよく知られている.

注意: ファイルを作るには他にも様々なひねくれた方法が考えられる. いろいろ考えてみよ.

とっておく必要のない出力を捨てることができる(しかも素早く).

やり方は次の表の通り.

sh 系 もしくは fish の場合 csh 系の場合
コマンド␣ &>␣/dev/null コマンド␣ >&␣/dev/null

このようにすれば,標準出力と標準エラー出力の両方がブラックホールへと消えていくことになる.

そんなことをしたくなる場面があるのか? と思うかもしれないが, これがあるのだ. 例えば, ジョブをバックグラウンドで実行させていて,その出力が邪魔な時や, コマンドを nohup で実行させる場合, プログラムの計算速度などを純粋に測定するためにデータの出力に時間がかかると困る時,などがそれにあたる.

他にも,デバッグ情報などを常にエラー出力に出すことにしておいて, 不要なときはエラー出力先を ''/dev/null'' にしておく,という使い方や、実行結果には興味が無いが実行時間に興味があるのでファイルアクセスを減らしたい、というような場合にも使える.

パイプ

原理的には,リダイレクションを使えば,

Program A (出力)→ ファイル →(入力) Program B

として複数のプログラムの入出力を ファイルを媒介して 繋げられる. しかし、その場でデータを受け渡す目的だけならばファイルを介するのは無駄だし遅い.

そこで, Program A の標準出力と Program B の標準入力を直接繋いでしまう方法 が unix には用意されている.

この同時リダイレクションとでもよぶべき方法は, 「パイプ」もしくは「パイプライン」と呼ばれ,次のように使う.

sh 系, csh 系, fish 意味
Program A ␣¦␣ Program B Program A の標準出力を Program B の標準入力として渡す.
Program A ␣¦&␣ Program B Program A の標準出力と標準エラー出力を
Program B の標準入力として渡す.

注意: なお、パイプは好きなだけ何段にも重ねることができる!! ので覚えておこう.

パイプの実例

例えば, ps␣axu の結果を画面で見るとしよう. そのままこのコマンドを実行すると, 大量のデータが出力されて画面上を流れていってしまうのは経験しているだろう. こういうときは,less コマンドなどを用いて,一画面ずつ表示させるのが定石である. それには

1ps axu | less

↑ ps コマンドの出力と less コマンドの入力を直接パイプで繋いでいる

とすればよい.

さらに,この結果をプロセスの名前順に並べ直すことによって見易くしたいな〜 と思ったとしよう. すると,sort コマンドを使って,上の結果を並べ直せば良い. それにはどうするかというと,パイプを二回使って,

1ps axu | sort -k 11 | less

↑ ps コマンドの出力と sort コマンドの入力をパイプで繋ぎ,さらに sort コマンドの出力と less コマンドの入力をパイプで繋いでいる(パイプを二段使っている)

注意: ps コマンドの結果の何番目にプロセス名が表示されるかも環境に依存する.自分で数えてから 実行しよう.

とすれば,

1osboxes     1667  0.0  0.0 104232  4392 ?        S    18:09   0:00 (sd-pam)
2osboxes     1666  0.2  0.1  19384 11504 ?        Ss   18:09   0:01 /lib/systemd/systemd --user
3root         270  0.3  0.4  74192 39328 ?        S<s  18:09   0:01 /lib/systemd/systemd-journald
4root         721  0.0  0.1  24932  8420 ?        Ss   18:09   0:00 /lib/systemd/systemd-logind
5systemd+     511  0.1  0.0  16008  7188 ?        Ss   18:09   0:00 /lib/systemd/systemd-oomd
6systemd+     512  0.0  0.1  19080 11236 ?        Ss   18:09   0:00 /lib/systemd/systemd-resolved
7systemd+     686  0.0  0.0  89500  6512 ?        Ssl  18:09   0:00 /lib/systemd/systemd-timesyncd
8root         317  0.0  0.0  27660  7516 ?        Ss   18:09   0:00 /lib/systemd/systemd-udevd
9  …略…

などと,プロセス名順に並んだ結果が画面上で一画面ずつ見られるというものだ.

  実習

  • 上に示した実例と同じ作業をやってみる.
  • さらに,パイプを三段使う例を考えて,実際に試してみよ.

覚えておくと便利なコマンド tee
出力を画面とファイルの両方に出力できるよ

リダイレクションやパイプを使うときに, 「ファイルにも取っておきたいけど, 画面で確認しながら作業できないので不安だ」 という思いがあると思う.
こういう時便利なのが tee コマンドで, 「標準入力を複製して,標準出力とファイルの両方に出力する」機能を持つ.

tee の実例

例として先の ls␣-lga の結果をファイルに収める例を考えてみよう.
この作業を先のやり方 ls␣-lga␣>␣file でやると, ''file'' の中身を見るまでどうなっているかわからない.

しかし,tee コマンドを用いて,

1ls -lga | tee sample-file

↑ ls コマンドの出力を標準出力に出しながら,かつ,sample-file というファイルにも出力する

とすると,結果は画面にも出力されつつ, sample-file という名前のファイルにも書込まれることになる.
慎重に作業を行ないたい,という時はこのコマンドを上手に使うのが良いだろう.

注意: 作業過程を記録しておく,という意味で似たようなものに script というコマンドがあることは紹介済みだ. どちらも使いこなし,適切に使い分けよう.



便利! 先読み評価(コマンド置換, command substitution)

シェルには,コマンド置換という便利な機能がある. これは,コマンド中の ` (バッククォート, 逆引用符) や $( ) , もしくは () などで囲んだ部分を「先に実行してその結果で置き換える」というものである. これによって,コマンドの出力結果をあたかも文字列のように扱える.

簡単に言えば,通常ならば分けて行なう複数の操作を一行に書ける ということである.


注: bash では `` や $() で囲んだところにコマンド置換が適用されて,fish だと () で囲んだところに適用される.

先読み評価(コマンド置換)の実例

例えば,test-日付 という名前のファイルを作りたいな〜 と思ったとしよう(日付部分は月日の4桁とか).

日付を得るには,date コマンドが使えるのでこれを使わない手はない. これはオプションを適当に指定すれば好きな形式で出力が得られる便利なコマンドで、 例えば date␣+%m%d とすれば 4桁の数字の形で「月」「日」が得られる.

そこで,bash/dash の場合は

1touch test-`date +%m%d`

とするか、

1touch test-$(date +%m%d)

とする.fish の場合は

1touch test-(date +%m%d)

とする.

↑ date コマンドの出力結果が文字列となる

すると,コマンド置換によって, data +%m%d という部分が先に実行されて,結果の4桁の数字に置き換えられる ため,test-0505 などという空っぽのファイルが作られることになる.

注意: テンポラリファイルを作る専用のコマンド mktemp が存在する.何か実際に作業する際には結構便利なので覚えておこう.

注意: コマンド置換の応用で,「○○というプロセスを kill する簡単なコマンド」というようなものも作ることができる. わざわざ ps␣axu コマンドで調べて〜 とやらずに済むので楽だ. 詳しい学生は少し考えてみよう(grep や awk を使うとよいだろう).

先読み評価の実例をもう一つ

もうちょっと複雑な例も考えてみよう. 例えば,t で始まるファイル名をもつファイルが今のディレクトリにいくつあるかざっとみておきたい, と思ったとしよう. すると,ls コマンドと wc コマンド(単語数を数える)を用いて

1ls t* | wc -w

とすれば,該当するファイルが 3つあれば 3 という答えが得られる(ディレクトリがあるとまた話が変わるよ).

しかし,数字だけしか表示されないので味気ない. そこで,echo コマンド(文字列を表示する)と組み合わせて, bash/dash の場合は

1echo "`ls t* | wc -w` t* files exist."

とするか、もしくは

1echo "$(ls t* | wc -w) t* files exist."

として,fish の場合は

1echo (ls t* | wc -w) "t* files exist."

とすると,コマンド置換によって, ls t | wc -w* 部分が先に実行されて,結果の数字に置き換えられる ため,例えば

1  3 t* files exist.

などという結果が表示されるようになる.

注意: こういう場合,単数形と複数形が異なるので,正しい英語にしたかったら面倒だ(^-^).

  実習

  • ''tee'' コマンドと先読み評価に関して, 上に示した実例と同じ作業をやってみよう.



別名(alias), 省略形(abbr) 設定

エイリアス(alias) とは,コマンドに「別名」をつける機能である. 通常のシェルにはたいていついている機能で,簡単なわりに便利だ.

こういった話は分類すればシェルの設定に含まれるが,CUI を使う上でなにしろ便利かつ重要なのでここで先に紹介しておこう.

以下、例をあげよう.

まずは bash の場合だ.

文法は簡単だ.

1alias 別名='本来のコマンド'

とすれば良い.

これを実行すればそのセッションでそれ以降は別名が有効になるし,この設定が気に入ったならば設定ファイルに書き込んでおけば次のシェル起動時からはいつでも有効だ.

下記で bash での alias の例を見てみよう.

目的等 aliasサンプル
タイピングの手間を減らし,ミスを少なくする 例) alias␣md='mkdir'
としておいて、md dummy とすると
dummy ディレクトリが作れる.
他の例) alias␣em='emacs'
複雑な動作を 1コマンドに短縮する(新しいコマンドを作る) 例) alias␣newfile='touch␣dummy-$(date␣+%m%d)'
コマンドのオプションを指定するなどして,デフォルト動作を変更する 例) 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'

次に fish の場合だ.

fish では別名(alias, コマンドに別の名前をつける)と省略形(abbr, 省略形で呼び出せ,実行時には展開されて元のコマンドが見える)の両方が使えるが,

省略形 abbr の方が利点が多く,おすすめ

だ.

  Youtube の動画に
  FISH (Friendly Interactive Shell) by Bash Boomer
というものがあり,fish の abbr が如何に便利かを主に説明しているので,ぜひ見ておくとよいだろう.

さて,文法はやはり簡単で,alias は

1alias 別名 本来のコマンド

とすれば良いし,abbr で省略形を追加する場合は

1abbr -a 省略形 本来のコマンド

とすれば良い. 他に詳しく知りたければ,たとえば

1help abbr

としてみよう.なんと web ブラウザにヘルプが出て(fish の特徴の一つ),細かいことまでわかるぞ.

さて,以下に例を挙げておこう.煩雑になるので,例としては abbr の方だけ書いておく.

目的等 abbr サンプル
タイピングの手間を減らし,ミスを少なくする 例) abbr␣-a␣md␣mkdir
としておいて、md dummy とすると
dummy ディレクトリが作れる.

他の例) abbr␣-a␣em␣emacs
複雑な動作を 1コマンドに短縮する(新しいコマンドを作る) 例)
abbr␣-a␣newfile␣touch␣dummy-(date␣+%m%d)
コマンドのオプションを指定するなどして,デフォルト動作を変更する 例) abbr␣-a␣cp␣cp␣-i
例) abbr␣-a␣mv␣mv␣-i
例) abbr␣-a␣rm␣rm␣-i
例) abbr␣-a␣man␣jman
例) abbr␣-a␣ls␣ls␣--color=auto␣-Fga
変数を設定する 例) abbr␣-a␣newpath␣PATH=hogehoge

alias, abbr の文法について一応のまとめ

alias, abbr の文法をまとめておこう.

alias 文法 (bashの場合)

機能 文法と解説
設定 alias␣別名='コマンド'
ただし,引数参照はできない…はず.
解除 unalias␣別名
表示 alias
関数設定 引数参照をしたいときは、alias の代わりに関数を使うと良い.
文法は以下のとおり.設定ファイルなどに書き込んで使う.

新関数名(){

内容… ;
内容… ;
}

この関数では、n 番目の引数を $n として参照できる.

alias文法 (csh系の場合)

機能 文法と解説
設定 alias␣別名␣'コマンド'

csh 系の場合,次のように書くと引数を alias 中で参照できる.
\!* (意味:全ての引数)
\!$ (意味:最後の引数)
\!:n (意味:n番目の引数)
解除 unalias␣別名
表示 alias

abbr 文法 (fishの場合)

機能 文法と解説
設定 abbr␣-a␣省略形␣コマンド
解除 abbr␣-e␣省略形
表示 abbr␣-s
なお,abbr␣-l でも良いがこちらは省略形のみが表示される.

  実習

  1. 上に示した abbr の例を一つで良いので実際に設定してみて,使ってみよう.その場で元のコマンドが展開される便利さ を味わってみよう.

  2. さらに,上に示した alias, abbr の例をなるべく多く試してみて,(余裕があれば)便利そうなものを以降に示す初期設定の方法を用いて初期設定せよ.

  3. (余裕がある者用) alias もしくは関数機能もしくは abbr を用いて,二つの引数の順番を逆にして表示するコマンド swap を作ってみよ.
    つまり, swap␣a␣b と入力すると, b␣a と表示されるような alias もしくは関数 swap を実現してみろ,ということである.



補足: シェルの設定等

自分に合わせてカスタマイズできるのが Unix のシェルの良いところだ. 以降,シェルの設定について一通り簡単に記しておこう.

ただし,よくわからなければ無理してカスタマイズしなくても良いわけなので,以降の補足情報はしばらくは無視しておく,というスタンスでも問題ないだろう.

シェルの設定ファイル

シェルおよびシェルから起動されるコマンドの動作の一部に影響を与える設定は, 以下のようなファイルの中に書いた設定で決まる.

sh 系の設定ファイル

ファイル名 解説
.bashrc bash を「非ログインシェルで対話的に」使う場合の設定を書くファイル.
下記の .bash_profile からも通常はこのファイルが読込まれる.
よって、端末設定とデフォルトコマンド起動以外はこのファイルに書込めばよい.
シェルの設定に関しては,通常はこのファイルをいじるだけで済むだろう.
.bash_profile bash を「ログインシェルで」使う場合の設定を書くファイル.
端末設定とデフォルトコマンド起動等をこのファイルで行なうのが正しい姿,だろう.
それ以外の設定は .bashrc を読込んで行なうようになっているのが普通.
.profile sh 系シェル共通に使える設定ファイル.
しかし,sh 系シェルを利用する人は現状では bash
を使う人が多いだろうから,
あまり出番はないだろう(^-^).
その他 .profile 中で変数 ENV に設定したファイルは対話環境では自動的に読込まれる.
しかしその機能を使う人は少ないか.

csh系の設定ファイル

ファイル名 解説
.tcshrc tcsh を使う場合,必ず読込まれるファイル.
環境によらず読込まれる.
共通に使える設定はこのファイルに書くと良い.
「端末設定とデフォルトコマンド起動」はこのファイルに書かないか,
環境を判定するやや複雑な設定を書くことになる.
まあ、普通はこのファイルを編集しているだけで済む.
.login ログイン時だけ,.(t)cshrc の読込みの後に読込まれるファイル.
端末設定とデフォルトコマンド起動はこのファイルに書込むのが良い.
詳しいことが分からないウチは触らない方がよいだろう.
.cshrc csh 系シェル共通に使える設定ファイル.
.tcshrc の代わりに使う人も多い.
その他 .tcshrc 中などで source コマンドを用いて別ファイルを読込む設定にすることも多い.
具体的には,alias コマンドだけを別ファイルにするなどの設定がよく見られる.

fish の設定ファイル

ファイル名 解説
~/.config/fish/config.fish fish が起動されるときに読込まれるファイル.
なかったら作ることも可.
もっと詳しく知りたかったら,fish に対して,"help" 1 とコマンドをいれてみよう.

変数の設定: シェル変数

シェルが固有に持つ変数をこう言う. シェル自身の動作にかかわる設定に用いられる. 名前は小文字で記述することが多い. 使い方等は以下のとおり.

意味 sh系 csh系 fish
作成, 代入 変数名=値 set␣変数名=値 set␣変数名 値
削除 unset␣変数名 同左 set␣-e␣変数名
表示 set 同左 同左
参照 $変数名 同左 同左

代表的なシェル変数

シェルがもつ独自の変数、シェル変数のうち、少しだけ紹介しておこう.

シェル変数 解説
PATH
(コマンドサーチパス)
コマンドを起動するときに,
どのディレクトリから探してくるのかをシェルに教えておくもの.
path に設定されているディレクトリにあるコマンドは,
コマンド名を入力するだけで使用できる.

よくわからないうちは追加のみを行うようにしておこう.

Windows にも同じ名前で同じ機能をもつ環境変数がある.
PS1: sh系, prompt: csh 系
(プロンプト)
コマンド入力行の先頭部分にシェルが表示する文字列のこと.
bash では例えば,
PS1="(BAsh)\H<\u>\[\033[1;34m\]\w\[\033[0m\] <\!>"
と入力すると、プロンプトがこの設定通りに変化する.
これをファイル .bashrc の中に記述して
source .bashrc
と入力するかログインし直しても良い.
HISTSIZE: sh系, history: csh系
(ヒストリ)
シェルが履歴(history)を取っておくコマンドの数.
少し多めにしておくとよいだろう.
ignoreeof, noclobber,noglob 等
(エラー処理,安全化系)
うっかりミスや知識不足によって発生する支障を予防する.
オンラインマニュアルで調べておこう.

もう少し詳しく知りたければ、 man␣bash もしくは man␣tcsh として,シェル変数の項目を読めばよい. びっくりするぐらいたくさんあるぞ.

変数の設定: 環境変数

シェルから起動されるコマンドの動作設定にかかわる変数をこういう. シェルだけでなく、いろんなコマンドが参照する前提だ. 名前は大文字で記述することが多い. 使い方等は以下のとおり.

意味 sh系 csh系 fish
作成, 代入 (シェル変数として作成した後) export␣変数名
もしくは、合わせて1行で exprot␣変数名=値 としてしまう方が良いかも.
setenv␣変数名␣値 set␣-x␣変数名␣値
削除 unset␣変数名 unsetenv␣変数名 set␣-e␣変数名
表示 set or env printenv set
参照 $変数名 同左 同左

代表的な環境変数

環境変数 解説
HOME
(ホームディレクトリ)
ユーザのホームディレクトリ.
Unix の場合はアカウント作成時に事実上設定されるので、いじらなくて良い.
Windows では自分で設定したほうが幸せになれるだろう.
EDITOR
(エディタ)
デフォルトのエディタ.
設定しておかないとおそらく vi が起動するので,
emacs あたりを設定しておくのがよい.
PAGER
(ページャ)
デフォルトの画面表示ソフト.
日本語に対応したものを設定しておくのがよい.
LANG
(言語)
デフォルトの言語.
プログラムがこの環境変数を見て適切に設定を変えてくれることがある.
C に設定しておくと無難だが、もちろん英語表記になる.
日本語を用いるならば,
Linux やFreeBSD では ja_JP.UTF-8ja_JP.eucJP などと設定すればよい.
TERM, TERMCAP
(端末属性)
端末の名前や性質を指定する.
何か設定しなければいけないという状態に追い込まれたら(^-^),
TERM に vt100 を設定しておけばとりあえずしのげるだろう.

設定ファイル修正の注意

シェルの設定ファイルを修正して,その効果をみるためにはどうしたらよいだろうか? いったんログアウトしてまたログインする? それは「危険」だ.

シェルの設定ファイルの修正中は絶対にログアウトや exit をするな!
修正に失敗すると二度とログインできなくなることがあるので、設定のミスが無くなるまでログアウトしないようにしよう.
もしそうなったら… 管理者に泣きつけばなんとかなるとは思うが…

シェルの設定ファイルを修正する時は、以下のように行動しよう.

  1. (後述の) source コマンドで設定ファイルが読み込まれたときの反応をしっかり確認する
  2. カスタマイズが終わるまで絶対にログアウトしない端末を一つは確保しておく
  3. 何か設定を変えたら別の端末(ソフト)からログインしてテストする(= 現在の端末(ソフト)はログアウトしない)

設定ファイルの読み込みコマンド: source

設定ファイルを修正した後,その場でその影響をみようとして「設定ファイルを読み込む」には,

1source ファイル名

とすればよい.
例えば、設定ファイルである .bashrc ファイルを読み込みたければ、

1source ./.bashrc

とする.
注意: セキュリティ対策の一環で、.(ピリオド)で始まるファイル名は直に指定すると無視される設定になっていることが多い. つまり、

1source .bashrc (← たぶん動かない)

とすると「そんなファイルは無いぜ」と言われてエラーになったりする. そのため、上では ./ をファイル名の前につけて source コマンドを使っている( . は「今居るディレクトリ」という意味).

注意: なお、素の sh は source コマンドが使えず,

1. ファイル名  (=ピリオド,空白, ファイル名)

という方法しか使えないそうだが…現在はもう気にしなくて良いだろう.

  実習

  1. 上に示した例をみながら,emacs などで ~/.bashrc ファイルを編集し,プロンプトだけでも変更してみよ.

    ~/.bashrc ファイルがそもそも無い場合は,touch コマンドなどで ~ ディレクトリにファイルを作ってから設定を書き込めば良い( ~ はユーザのホームディレクトリ).
    具体的には、 cd ~ ; touch .bashrc などとすればいいだろう.

  2. 余裕のある者はさらに,シェルのオンラインマニュアルなどを参考にしていろいろ設定してみよう.

デフォルトコマンド起動

bash ならば .bash_profile で, csh 系ならば .login で,ログイン時に起動されるコマンドを書いておく, ということもできる.

これをうまく使って,例えば起動時に

  • ディスクの(自分の)使用量を調べる.
  • メールが来ているか調べる.
  • 今日の運勢を占う(^-^).
  • ○○さんが大学のマシンにログインしているか調べる.
  • やらないといけない仕事を表示する(ToT)

などということができる. まあ,今時はこれらの機能はそんなにありがたくないが、知っていると助かることもあるだろう.

  実習

  • ログインするたびに, You use xxx MB in this system. という感じで, ユーザ個人のディスク使用量が表示されるようにしてみよう.
    なお,du というコマンドを使うと良い. ただし,オプションは慎重に設定しよう.

レポート

以下の課題についてなるべく頑張って調査と考察を行い,
2024-AppliedMath7-Report-04
という題名をつけて e-mail にて教官宛にレポートとして提出しよう. なお,レポートを e-mail の代わりに TeX で作成した書面にて提出してもよい.

  注意
  近年はセキュリティ上の懸念から,実行形式のプログラムなどをメールに添付するとそのメールそのものの受信を受信側サーバが拒絶したりする. そういうことを避けるため,レポートをメールで提出するときは添付ファイルにそういった懸念のあるファイルが無いようにしよう.

まあ要するに,レポートは pdf ファイルにして,それをメールに添付して送るのが良い ということだと思っておこう.

課題

  1. 本資料の実習部分をすべて行い,それについて報告せよ. やりました,と書くだけではなくて,script コマンドを用いて記録を示そう.

  2. パイプと組み合わせて上手に使うと便利そうなコマンドを紹介せよ.

  3. alias もしくは abbr を用いて便利な 別名/短縮 コマンドを自分なりに考えてみよう.可能ならばそれらをいつも使えるようにシェルの設定ファイルに書き込もう.

  4. 「今日の日記を書くためにエディタが起動する」コマンドを用意せよ.
    具体的には,その日の日付がついたテキストファイルをエディタが開くという程度でよい.

  5. シェルのプロンプト設定を「便利になるように」設定せよ.
    とくに fish を使う場合はかなり「かっこよく?」できるので,いろいろ試してみると良い.

  1. fish に対して "help" と打つとなんと web browser でマニュアルを見せてくれる.初めて見るときにはちょっと驚くぞ. ↩︎