IT pass HikiWiki - [itbase2022]シェル Diff

  • Added parts are displayed like this.
  • Deleted parts are displayed like this.

= シェル

計算機を管理・操作するための基本ソフトウェアである OS (Operating System) は,
ユーザからの様々な要求を受け付け, それを処理します.
しかし, その OS は, 実は一つのソフトウェアではなく, 大きく分けて二つの部分から構成されています.
一つはカーネル (kernel) と呼ばれ, 一つはシェル (shell) と呼ばれるものです.

イメージとしては, 文字通りカーネルは「核」であり, 処理の中核を担います.
シェルは「殻」として, 外=ユーザやアプリケーションとのやり取りを担当しています.
したがって, ユーザがターミナルから入力したコマンドは, OS の中のシェルが
受け付け, シェルがカーネルとやり取りしながら処理されます.

ユーザとのやり取りを担うシェルについては, 世界中のプログラマーが便利に使うために
複数の種類を開発してきました.
例えば, sh (一番原始的なシェル; shell の略), bash, csh, tcsh, zsh, ... などがあります.
近年普及しているのは bash (「バッシュ」と発音される) です.
情報基盤センターの計算機のデフォルトシェルも bash になっていますので, 以下では,
bash について説明していきます.
(「デフォルト」とは特別な設定をしていない状態を意味します.)
(macOS では, macOS 10.15 Catalina から zsh をデフォルトシェルとしているようです. 以下の bash に関する説明は基本的なものなので, zsh でも共通でしょう.)

シェルはユーザの利便性のためにたくさんの便利な機能を持っています.
下では, シェルの他の役割の一部について簡単に実習します.

== エイリアス (別名)

良く使うコマンドや長い名前のコマンドに, (打ちやすい/短い) 別名を
付けると便利なことがあります. ある意味ではショートカットのような
ものかもしれません.
その別名を付けるコマンドが alias で, 下のように別名を付けます.

  alias 別名=コマンド名
  alias 別名='オプション付きのコマンド名'

例えば, ls -l に別名を付けてみましょう.

  $ ls -l                           <- 別名を付ける前の動作. ファイルのリストを表示
  合計 1520
  drwx------ 2  XXX student 4096 Mar 28 12:47 Desktop
  drwx------ 2  XXX student  256 Mar  7 2005  Documents
  drwx------ 23 XXX student 4096 Apr  4 14:47 Library
  ...

  $ alias ll='ls -l'                <- ls -l に ll という別名を付ける
  $ ll                              <- コマンド ll を実行
  合計 1520
  drwx------ 2  XXX student 4096 Mar 28 12:47 Desktop
  drwx------ 2  XXX student  256 Mar  7 2005  Documents
  drwx------ 23 XXX student 4096 Apr  4 14:47 Library
  ...

上に示したように, 別名を付けることで自分で新たなコマンドを作ることができます.

また, 別名がつけられたコマンドを確認するためには, オプションや引数なしで
alias を実行します.

  $ alias                     <- オプション, 引数なしで実行
  alias ll='ls -l'
  alias ls='ls --color=auto'

上の例では, ls と打つだけで ls --color=auto が実行される設定になっています.

なお, 別名を解除するためには unalias を使います.
例えば,

  $ unalias ll                  <- 別名解除
  $ ll                          <- ll を実行してみる
  bash: ll: command not found

のように, ll は機能しなくなります.


alias を使ってよくやる設定の一つは rm の別名です.
rm はファイルを削除するために使うのでした.
例えば,

  $ echo "hello world" > hello.txt         <-- hello.txt ファイルを作成
  $ rm hello.txt                           <-- hello.txt ファイルを削除

とすることで, hello.txt を消すことができます.
ここで, rm に i オプションをつけてみましょう.

  $ echo "hello world" > hello.txt
  $ rm -i hello.txt
  rm: remove regular file ‘hello.txt’?   <-- 削除するならば y を押し, 削除しないならば n を押します.

rm に i オプションを付けることで, 上のように, 削除を確認してくれるようになります.
この rm -i に下のように別名をつけることが良くあります.

  $ alias rm='rm -i'                   <-- rm -i に rm の別名を付ける. 今後は rm とすると rm -i が実行される.
  $ echo "hello world" > hello.txt
  $ rm hello.txt
  rm: remove regular file `hello.txt'?

Unix/Linux に慣れてくると, 油断して, つい重要なファイルを消してしまうことが
良くあります.
上のように設定しておくと, そのようなミスを避けることができるかも
しれません (できないかもしれませんが).

しかし一方で, 大量のファイルをいっぺんに消す時には, いちいち削除を確認
されると面倒なものです.
例えば,

  $ ls
  $ touch hoge1.txt hoge2.txt         <-- 空のファイル hoge1.txt, hoge2.txt を作成する
  $ ls
  ... hoge1.txt   hoge2.txt  ...      <-- ファイルができている
  $ rm hoge?.txt                      <-- hoge1.txt, hoge2.txt を削除 ("?" は任意の一文字を表すため, hoge1.txt, hoge2.txt の両方が指定されます.)
  rm: remove regular empty file 'hoge1.txt'? y
  rm: remove regular empty file 'hoge2.txt'? y

のように, ファイルの数だけ確認されます.
これを避けるには,

  $ unalias rm

によって別名設定を解除するか, rm に下のようにオプションを付けます.

  $ rm -f hoge?.txt

=== *注意1*

unalias によって設定を解除すると, 当然ながら, そのターミナルでは i オプションは設定されていないことに気を付けてください.
また, f オプションを付けると, 別名を付けていても削除を確認しないようになります.
-f オプションは, *問答無用で* 指定されたファイルを削除します.
(ファイルは二度と戻ってきません復元できません.)
ワイルドカード ("*" や "?") の指定と合わせて間違って rm を実行すると
「破滅的な事態」にもなりますので十分に気を付けてください.



なお, mv, cp にも同じように i オプションが存在します.
mv, cp では, 移動先およびコピー先に同名のファイルが存在する場合に
本当に上書きするのかどうか確認されるようになります.


=== *注意2*

ここで述べたエイリアスの設定は, 現在使っているターミナル (正確には
シェル) のみでしか通用しません.
新しいターミナルを立ち上げたときには, そのターミナルでは上の alias の設定が
引き継がれません.
すべてのターミナルで alias の設定をするには, シェルの
設定ファイルに alias を書いておく必要があります.
設定ファイルへの alias の書き込みについては, エディタ (emacs) の項目で
説明します.


== ヒストリー (履歴)

たくさんのコマンドを入力していくと, 「前に打ったコマンドをもう一度入力したい」と思うことがあるでしょう.
シェルには, 過去に入力したコマンドを記憶しておく機能があります.

例えば, ひとつ前に実行したコマンドをもう一度実行するには,
ターミナルで, [↑] (上矢印) キーを押してみましょう.
ターミナルに, ひとつ前に実行したコマンドが表示されるはずです.
そこで [Enter] を押せばコマンドが実行されます.

  $                  <- ここで, [↑]キーを押すと過去のコマンドが表示される

もし, 二つ前に実行したコマンドを実行するには, [↑] を二回押しましょう.
三つ前に実行したコマンドを実行するには, [↑] を三回押しましょう.
四つ前...
のように, ある程度は過去のコマンドを遡って使うことができます.
なお, もし行き過ぎてしまったら [↓] (下矢印) キーを押して戻ることもできます.

さらに, 上の方法で戻って表示されたコマンドは編集することができます.
表示されたコマンドの一部を書き直したければ, そこだけ消して新しく
書き直せば, 手間を省けるでしょう.

また, 上では, 矢印キーを使っていますが,
[↑] の代わりに C-p ([Ctrl] キーを押しながら p を押す),
[↓] の代わりに C-n ([Ctrl] キーを押しながら n を押す) ことでも同じように動作します.


ところで, もうずっと前に入力したコマンドをもう一度実行したいこともあるでしょう.
そんな時には, history コマンドが役に立つかもしれません.
history コマンドは, 過去に入力したコマンドを表示します.

  $ history
  ...
  504  cd work
  505  ls -l
  506  cd mpidir/
  507  ls -l
  508  mkdir dir
  509  cd dir/
  510  touch file
  511  history

このとき, 過去に実行したコマンドをもう一度実行したければ

  $ ![番号]

と入力します. 例えば 508 番のコマンドをもう一度実行したい場合には,

  $ !508
  mkdir dir            <- 実行されたコマンドが表示される

となり, 実行されます.

== 補完

長い名前のファイルやディレクトリを指定する際に, 名前のすべてを打つのが
大変なこともあるでしょう.
シェルには, [Tab] キーを使って, ファイル名やディレクトリ名を補完する
機能があります.

例えば, 下のようなファイルやディレクトリがある場合を考えましょう.

  $ ls
  Desktop   Document   Movies

このとき, Movies ディレクトリの中に入っているファイルやディレクトリを
調べたい時には,

  $ ls Movies

と打ちますが, シェルの補完機能を使えば, "M", "o", "v", "i", "e", "s" の
すべてのアルファベットキーを打つ必要はありません.
今あるファイルやディレクトリの中で, "Movies" を指定するには,
頭文字の "M" だけわかれば一意に決まります. したがって, "M" の後に
[Tab] を打ち,

  $ ls M[Tab]    <- "[Tab]" は非表示. M と [Tab] の間に空白は入れない.

とすると, 自動的に Movies を特定して,

  $ ls Movies

と表示してくれます.

なお, もし

  $ ls D[Tab]

と打つと, カレントディレクトリにある Desktop と Document のどちらなのかは
まだ特定できないため, 何も表示されません.
しかし,

  $ ls D[Tab][Tab][Tab]   <- [Tab] を 3 回続けて打つ (2 回でよいかもしれないけれど). "[Tab]" は非表示.

のように [Tab] を続けて打つと, 下のように, ここまでに入力済みの文字と整合的な候補となるファイルやディレクトリを表示します.

  $ ls D[Tab][Tab][Tab]   <- "[Tab]" は非表示.
  Desktop   Document

上の例では, D から始まるファイルやディレクトリを指定しているので, Movies は
表示されません.
ここで次の文字, 下のように, 例えば "o" を打って [Tab] を押すと,

  $ ls Do[Tab]            <- "[Tab]" は非表示.



  $ ls Document

となり, Document を特定して表示します.

この補完機能を使うとキータイプを素早く行うことができるでしょう.


== 説明していないこと (メモ)

今回は時間の関係で説明しないが, 興味があれば調べてみると良いでしょう.

* 過去のコマンドの検索 (C-r)
* シェル変数, 環境変数.