第1章 GNU/Linux チュートリアル

# 第1章 GNU/Linux チュートリアル

コンピューターシステムを学ぶことは新しい外国語を学ぶことに似ていると考えます。チュートリアルブックは有用ですが、実際に自ら使って学ぶことが必要です。円滑なスタートが出きるように、いくつかの基本的なポイントを説明します。

Debian GNU/Linux の強力なデザインはマルチユーザー、マルチタスクという Unix オペレーティングシステムに由来します。これら Unix と GNU/Linux の特徴や類似点の強力さを活用することを覚えましょう。

Unix 対象の文書を避けたり、GNU/Linux に関する文書だけに頼ることは、有用な情報を見逃すことになるので止めましょう。

| 注記
Unix 的システムをコマンドラインツールで少々使った経験があれば、私がここで説明することはすべてご存知でしょう。リアリティーチェックと記憶を呼び戻すのにこれを使って下さい。

## 1.1. コンソールの基礎

### 1.1.1. シェルプロンプト

GNOME や KDE 等のデスクトップシステム等のような GUI 環境をインストールした場合以外には、システム起動の際に文字の login スクリーンが現れます。あなたのホスト名が `foo` と仮定すると、login プロンプトは次に示すような見えます。

GUI 環境をインストールした場合でも、Ctrl-Alt-F3 で文字ベースのログインプロンプトが出ますし、Ctrl-Alt-F2 で GUI 環境に戻れます (詳細は下記の「仮想コンソール」を参照下さい)。

    foo login:

login プロンプトであなたのユーザー名 (例えば `penguin`) を打鍵し Enter キーを押します。さらにあなたのパスワードを打鍵し Enter キーを再び押します。

| 注記
Unix の伝統に従い、Debian システムではユーザー名とパスワードに関して大文字小文字の区別をします。ユーザー名は通常小文字のみから選ばれます。最初のユーザーアカウントは通常インストールの際に作られます。追加のユーザーアカウントは root によって `adduser`(8) を用いて作られます。

"`/etc/motd`" (本日のメッセージ: Message Of The Day) に保存されている歓迎メッセージとコマンドプロンプトを表示しシステムが起動されます。

    Debian GNU/Linux 12 foo tty3

    foo login: penguin
    Password:

    Linux foo 6.5.0-0.deb12.4-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.5.10-1~bpo12+1 (2023-11-23) x86_64

    The programs included with the Debian GNU/Linux system are free software;
    the exact distribution terms for each program are described in the
    individual files in /usr/share/doc/*/copyright.

    Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
    permitted by applicable law.

    Last login: Wed Dec 20 09:39:00 JST 2023 on tty3
    foo:~$

これであなたはシェルの中にいます。シェルはあなたからのコマンドを解釈します。

### 1.1.2. GUI の下でのシェルプロンプト

インストールの際に GUI 環境をインストールした場合、システム起動時にグラフィカルなログイン画面が表示されます。あなたのユーザー名とパスワードを入力することで非特権ユーザーアカウントにログインできます。タブ (tab) を用いたりマウスの第一クリックを用いるとユーザー名とパスワードの間を行き来できます。

`gnome-terminal`(1) や `rxvt`(1) や `xterm`(1) のような `x-terminal-emulator` プログラムを GUI 環境下で起動するとシェルプロンプトが得られます。GNOME デスクトップ環境下では、"Applications" → "Accessories" → "Terminal" とクリックしてもうまくいきます。

デスクトップ環境 (例えば `fluxbox`) 次第ではメニューの起点がよく分からないことがあります。そんな時はデスクトップスクリーンの背景を (右)クリックしてメニューが表示されることを期待しましょう。

### 1.1.3. root アカウント

root アカウントはスーパーユーザーとか特権ユーザーとも呼ばれます。このアカウントからは以下のようなシステム管理活動ができます。

- ファイルパーミッションによらずシステム上の任意ファイルに関しての、読出しと書込みと削除

- システム上のいかなるファイルに関して、ファイルの所有者やパーミッション設定

- システム上の非特権ユーザーのパスワードを設定

- パスワード無しに任意アカウントへの login

root アカウントの権限を使うには、この無制限の権限ゆえ配慮と責任ある行動が求められます。

| 警告
root のパスワードを第三者に決して教えてはいけません。

| 注記
ファイル (Debian システムにとってはファイルの一種である CD-ROM 等のハードウエアーデバイスも含む) パーミッションは、非 root ユーザーによるそのファイルの使用やアクセスをできなくなくすることがあります。この様な状況の下では root アカウントを使うことが簡便なテスト法ですが、問題解決はファイルパーミッションとユーザーのグループのメンバーシップを適正に設定する必要があります (「ファイルシステムのパーミッション」を参照下さい)。

### 1.1.4. root シェルプロンプト

root のパスワードを使って root のシェルプロンプトを使えるようにする基本的な方法を次に記します。

- 文字ベースのログインプロンプトに `root` と入力します。

- どのユーザーシェルプロンプトからでも "`su -l`" と入力します。

  - 現ユーザーの環境を一切引き継がません。

- どのユーザーシェルプロンプトからでも "`su`" と入力します。

  - 現ユーザーの環境を一部引き継ぐ。

### 1.1.5. GUI のシステム管理ツール

デスクトップのメニューが GUI のシステム管理ツールを適切な権限とともに自動的に起動しない場合、`gnome-terminal`(1) や `rxvt`(1) や `xterm`(1) のような X ターミナルエミュレーターの root シェルプロンプトから起動できます。「root シェルプロンプト」 and 「Xサーバ接続」を参照下さい。

| 警告
`gdm3`(1) 等のディスプレーマネージャーのプロンプトに `root` と入力して、GUIディスプレー / セッションマネージャーを root アカウントのもとで決して起動してはいけません。 あなたの X スクリーンを覗き見られるかもしれないので、X Window 下で信頼できないリモートの GUI プログラムを決して実行してはいけません。

### 1.1.6. 仮想コンソール

デフォルトの Debian システムでは、6つの切り替え可能な VT100 様の文字コンソールが利用でき、Linux ホスト上で直接コマンドシェルを起動できます。GUI 環境下でない場合は、`Left-Alt-key` と `F1` — `F6` の中の一つのキーを同時に押すことで仮想コンソール間の切り替えができます。それぞれの文字コンソールはアカウントに独立してログインすることができ、マルチユーザー環境を提供します。このマルチユーザー環境は Unix の素晴らしい機能で、癖になります。

GUI 環境下では、`Ctrl-Alt-F3` キーを押す、つまり `left-Ctrl-key` と `left-Alt-key` と `F3-key` キーを同時に押すと文字コンソール3にアクセスできます。普通仮想コンソール2で実行されている GUI 環境には `Alt-F2` を押すことにより戻れます。

これとは別の方法で、例えば仮想ターミナル3という今とは違う仮想ターミナルへの変更がコマンドラインから出来ます。

    # chvt 3

### 1.1.7. コマンドプロンプトからの退出方法

コマンドプロンプトで `Ctrl-D`、つまり `left-Ctrl-key` と `d-key` の同時押しをするとシェルでの活動を終了できます。文字コンソールの場合は、こうすると login プロンプト戻ります。これらのコントロール文字は "control D" と大文字を使って表記されますが、Shift キーを押す必要はありません。また `Ctrl-D` に関する簡略表記 `^D` も使われます。この代わりに "exit" とタイプすることができます。

`x-terminal-emulator`(1) にあっては、このようにすることで `x-terminal-emulator` のウィンドウが閉じることができます。

### 1.1.8. システムをシャットダウンする方法

ファイル操作の際にパーフォーマンス向上のためにメモリーへのデーターのキャッシュがされる他の現代的な OS と同様に、Debian システムでも電源を安全に切る前に適正なシャットダウン手順を取る必要があります。これはすべてのメモリー上の変更を強制的にディスクに書き出しすことで、ファイルの完全性を維持するためです。ソフトウェアー電源コントロールが利用できる場合、シャットダウン手続きはシステムの電源を自動的に落とします。(これがうまくいかない時には、シャットダウン手続きの後で数秒間電源ボタンを押す必要があるかもしれません。)

普通のマルチユーザーモードからのシステムのシャットダウンがコマンドラインから出来ます。

    # shutdown -h now

シングルユーザーモードからのシステムのシャットダウンがコマンドラインから出来ます。

    # poweroff -i -f

「SSH 上のリモートシステムをシャットダウンする方法」を参照下さい。

### 1.1.9. 合理的なコンソールの復元

例えば "`cat some-binary-file`" のような変な事をした後でスクリーンが無茶苦茶になった場合、コマンドプロンプトに "`reset`" と入力して下さい。このときコマンドを入力してもスクリーンには読み取れる表示がされないかもしれません。"`clear`" とすればスクリーンが消去できます。

### 1.1.10. 初心者向け追加パッケージの提案

デスクトップ環境タスク抜きの最小限インストレーション Debian システムですら基本的な Unix 機能は提供されますが、コマンドラインや curses に基づく `mc` や `vim` 等のいくつかの文字ターミナルパッケージを `apt-get`(8) を使って以下のように追加インストールすることから始めることを初心者にお薦めします。

    # apt-get update
     ...
    # apt-get install mc vim sudo aptitude
     ...

既にこれらのパッケージがインストールされている場合には、新しいパッケージはインストールされません。

表1.1 興味あるテキストモードのプログラムパッケージのリスト

パッケージ | ポプコン | サイズ | 説明
--- | --- | --- | ---
`mc` | V:43, I:183 | 1590 | テキストモードの全画面ファイルマネージャー
`sudo` | V:732, I:863 | 6773 | ユーザーに限定的な root 権限を与えるプログラム
`vim` | V:86, I:346 | 4089 | Unix テキストエディター Vi IMproved (改良版 Vi)、プログラマーのためのテキストエディター (標準版)
`vim-tiny` | V:57, I:978 | 1877 | Unix テキストエディター Vi IMproved (改良版 Vi)、プログラマーのためのテキストエディター (軽量版)
`emacs-nox` | V:3, I:13 | 46536 | GNU プロジェクト Emacs、Lisp に基づく拡張可能なテキストエディター
`w3m` | V:11, I:145 | 2853 | テキストモード WWW ブラウザー
`gpm` | V:9, I:9 | 526 | テキストコンソール上の Unix 式のカットアンドペースト (daemon)

いくつかの参考資料を読むのも良いことです。

表1.2 有用な文書パッケージのリスト

パッケージ | ポプコン | サイズ | 説明
--- | --- | --- | ---
`doc-debian` | I:882 | 187 | Debian プロジェクトの文書、(Debian FAQ) 他
`debian-policy` | I:8 | 5061 | Debian ポリシーマニュアルと関連文書
`developers-reference` | V:0, I:2 | 2601 | Debian 開発者のためのガイドラインと情報
`debmake-doc` | I:0 | 11807 | Debian メンテナ向けガイド
`debian-history` | I:0 | 6251 | Debian プロジェクトの歴史
`debian-faq` | I:880 | 791 | Debian FAQ (よくある質問集)

これらのパッケージの一部を以下のようにしてインストールします。

    # apt-get install package_name

### 1.1.11. 追加のユーザーアカウント

以下の練習のためにあなたのメインのユーザーアカウントを使いたくない場合には、例えば `fish` という追加のユーザーアカウントを作ります。root シェルプロンプトで以下のように入力します。

    # adduser fish

すべての質問に返事をします。

こうすることで `fish` という名前の新規アカウントが作られます。練習の後で、このユーザーとそのホームディレクトリーは以下のようのすれば削除できます。

    # deluser --remove-home fish

非Debian や 特殊な Debian システム上では、より下層の `useradd`(8) や `userdel`(8) ユーティリティーで上記の操作を代用する必要があります。

### 1.1.12. sudo の設定

ラップトップ PC 上のデスクトップの Debian システム等のような典型的単一ユーザーワークステーションでは以下のような単純な `sudo`(8) の設定をして、非特権ユーザー (例えば `penguin`) に管理者権限を (root パスワードではなく) ユーザー自身のパスワードで与えることがよくあります。

    # echo "penguin  ALL=(ALL) ALL" >> /etc/sudoers

これに代え、以下のようにして非特権ユーザー `penguin` にパスワード一切無しに管理者権限を与えることもよくあります。

    # echo "penguin  ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers

ワークステーション上であなた自身が管理者で唯一のユーザーである場合にのみ、このトリックを使用して下さい。

| 警告
システムセキュリティー上非常に悪い事態を招くので、ユーザが複数いるワークステーション上で通常のユーザーアカウントに対してこの様な設定をしてはいけません。

| 注意
上記例のような `penguin` のパスワードとアカウントは root パスワードや root アカウント同様の保護が必要です。 この文脈上の管理者権限はワークステーションに関するシステム管理業務をする権限を与えられた人に属します。そのような権限と能力を持っていなければ、あなたの会社の管理部門の管理職や上司とはいえこのような権限を与えてはいけません。

| 注記
特定デバイスや特定ファイルへのアクセスの権限を与えるには、`sudo`(8) をつかって得た `root` 権限を用いるのではなく、group を使って限定的アクセス与えることを考えるべきです。 `sudo`(8) を使ってもう少し工夫された注意深い設定をすれば、共有システム上の他のユーザーに root パスワードを教えること無く限定的管理権限を許可することができます。こうすることは、誰が何をしたかを明らかにするので、複数の管理者がいるホストにおける責任の所在を明らかにします。ただ、誰にもそんな権限を与えたく無いかもしれません。

### 1.1.13. お遊びの時間

非特権ユーザーアカウントを使う限り全くリスク無く Debian システムでお遊びをする準備万端です。

何故なら、たとえデフォルトのインストール後でも、Debian システムには適正なファイルパーミッションが設定されていて、非特権ユーザーがシステムに損害を与えられないようなっているからです。もちろん悪用可能な穴が残っているかもしれませんが、こんな問題まで心配する人はこのセクションを読んでいる場合ではなく、Securing Debian Manual を読むべきです。

Debian システムを Unix 的システムとして次に学びましょう。

- 「Unix-like ファイルシステム」 (基本コンセプト)

- 「ミッドナイトコマンダー (MC)」 (サバイバル手法)

- 「基本の Unix 的作業環境」 (基本手法)

- 「シェルプロンプト」 (シェルのメカニズム)

- 「Unix 的テキスト処理」 (文字処理手法)

## 1.2. Unix-like ファイルシステム

GNU/Linux や他の Unix 的オペレーティングシステムでは、ファイルはディレクトリーに整理されています。すべてのファイルやディレクトリーは、"`/`"を根 (root) に持つ一本の大きな木 (ツリー) のようにアレンジされています。

このようなファイルやディレクトリーはいくつかのデバイスに展開することができます。あるデバイス上にあるファイルシステムを大きなファイルツリーにマウントするのに `mount`(8) が使われます。その逆に、それを切り離すのに `umount`(8) が使われます。最近の Linux カーネルでは、`mount`(8) をオプションとともに用いると、ファイルツリーの一部を別のところと結びつけたり、ファイルシステムを共有か非共有か従属かバインド不可としてマウントもできます。各ファイルシステムごとの利用可能なマウントオプションは "`/usr/share/doc/linux-doc-*/Documentation/filesystems/`" にあります。

Unix システム上のディレクトリーは、一部の他システム上ではフォルダと呼ばれます。Unix システム上では "`A:`" のようなドライブというコンセプトが無いこと覚えておいて下さい。単一のファイルシステムがあって、そこにすべてが含まれています。これは Windows と比べた際の大きな利点です。

### 1.2.1. Unix ファイルの基礎

Unix ファイルの基礎は以下です。

- ファイル名は大文字と小文字を区別します。"`MYFILE`" と "`MyFile`" は異なるファイルです。

- ルートディレクトリーはフィルシステムの根 (ルート、root) を意味して、単に "`/`" と記載されます。これを root ユーザーのホームディレクトリー "`/root`" とは混同しないで下さい。

- 全てのディレクトリーには "`/`" 以外の文字か記号からなる名前がついています。ルートディレクトリーは例外で、その名前は "`/`" ("スラッシュ" とか "ルートディレクトリー" と読まれます) でその名前を変えることはできません。

- 各ファイルやディレクトリーは、たどっていくとファイルに到達するディレクトリーの列が示される、完全に記述したファイル名とか絶対ファイル名とかパスにより指定されます。これらの3つの表現は同義語です。

- 全ての完全に記述したファイル名は "`/`" ディレクトリーで始まり、ファイル名中の各ディレクトリーやファイル名の間には "`/`" がはさまります。最初の "`/`" はディレクトリー名です。その他の "`/`" は、以下のサブディレクトリーとの区別をします。そして最後には実際のファイルの名前がきます。ちょっと混乱しそうですので、以下の完全に記述したファイル名 の例をご覧下さい: "`/usr/share/keytables/us.map.gz`"。 一方このベース名である、"`us.map.gz`" だけをファイル名と呼ぶ人もあります。

- ルートファイルシステムは "`/etc/`" や "`/usr/`" のような複数の枝を持ちます。これらのサブディレクトリーもまた "`/etc/systemd/`" や "`/usr/local/`" のように、さらにサブディレクトリーに枝別れします。これらの全体をまとめてディレクトリーツリーと呼びます。絶対ファイル名はツリーの根元 ("`/`") から枝の先 (ファイル) までの経路として考えることもできます。また、あたかもディレクトリーツリーをルートディレクトリー ("`/`") という単一人物の全直系に広がる家系図のように人が話すのを聞いたことがあるでしょう。あたかもそれぞれのサブディレクトリーに親があるとし、パスはファイルの完全な祖先の系図のように表現します。ルートディレクトリーではない他の場所から始まる相対パスもあります。ディレクトリー "`../`" は親ディレクトリーを参照していることを覚えておきましょう。このような呼び方はディレクトリーのような構造を持つ他の階層的ツリー状のデーター構造体でもよく使われます。

- ハードディスクのような物理デバイスに対応したパス名の要素は存在しません。ここが、パス名に "`C:\`" のようなデバイス名が含まれる RT-11 や CP/M や OpenVMS や MS-DOS や AmigaOS や Microsoft Windows と違う点です。(但し、普通のファイルシステム中に物理デバイスを示すディレクトリー項目はあります。「ファイルシステムの内側」を参照下さい。)

| 注記
ほとんど全ての文字や記号をファイル名中に使えますが、実際そうすることは賢明ではありません。スペースやタブや改行や他の特殊文字: `{ } ( ) [ ] ' ` " \ / > < | ; ! # & ^ * % @ $` はコマンドラインで特別な意味を持つので避けるべきです。名前の中の単語間には、ピリオドやハイフンや下線を選んで区別します。各語頭を "`LikeThis`" のように語頭を大文字にすることもできます。経験を積んだ Linux のユーザーはファイル名中にスペースが入ることを避けます。

| 注記
"root" (ルート) と言う言葉は "root ユーザー" と言う意味でも "ルートディレクトリー" と言う意味でも使われます。それがいずれかは使われている文脈から明かです。

| 注記
パスと言う言葉は上述の完全に記述したファイル名に関して使われるばかりではなくコマンドサーチパスにも使われます。どちらの意味かは文脈から通常明かです。

ファイル階層について詳細に学ぶ最も良い方法は、Filesystem Hierarchy Standard ("`/usr/share/doc/debian-policy/fhs/fhs-2.3.txt.gz`" や `hier`(7)) に記述されています。手始めとして以下の事実を覚えるべきです。

表1.3 重要ディレクトリーの使い方のリスト

ディレクトリー | ディレクトリーの用途
--- | ---
`/` | ルートディレクトリー
`/etc/` | システム全体の設定ファイル
`/var/log/` | システムのログファイル
`/home/` | 全ての非特権ユーザーのホームディレクトリー

### 1.2.2. ファイルシステムの内側

Unix の伝統に従い、Debian/Linux システムはハードディスクや他のストレージデバイス上に存在する物理データーを表す ファイルシステムを提供し、コンソールスクリーンやリモートのシリアルコンソールなどのハードウェアデバイスとの相互作用が "`/dev/`" の下に統一された形式で表されています。

Debian/Linux システム上の、各々のファイルやディレクトリーや名前付きパイプ (2つのプログラムがデーターを共有する方法) や物理デバイスは、それぞれの所有者 (owner) やデーターが所属するグループ (group) や最終アクセス時間などの付帯属性 (attribute) を記述する inode と呼ばれるデーター構造を持ちます。 ほとんど全てをファイルシステム表現しようというアイデアは Unix の発明でしたし、現代的な Linux カーネルはこのアイデアを一歩進めています。コンピューター上で実行されているプロセス情報さえファイルシステム中に見つけられます。

このような物理的実体と内部プロセスの抽象的かつ統一された表現は非常にパワフルなので、多くの全く異なるデバイスに同じコマンドを使用して同種の操作が行えます。実行中のプロセスに繋がった特殊なファイルにデーターを書き込むことでカーネルが如何に動作するかまで変更できます。

| ヒント
ファイルツリーや物理的実体の間の関係を確認する必要がある際には、`mount`(8) を引数無しで実行して下さい。

### 1.2.3. ファイルシステムのパーミッション

Unix 的システムのファイルシステムのパーミッションは以下の3つの影響されるユーザーのカテゴリーのために定義されています。

- ファイルを所有するユーザー (user) (u)

- ファイルが所属するグループ (group) 中の他ユーザー (g)

- "世界" や "全員" とも呼ばれる、全第三者 (other) ユーザー (o)

ファイルでは、それぞれに対応するパーミッションは以下のようになります。

- 読出し (read) (r) パーミッションはファイル内容確認を可能にします。

- 書込み (write) (w) パーミッションはファイル内容変更を可能にします。

- 実行 (execute) (x) パーミッションはファイルをコマンド実行を可能にします。

ディレクトリーでは、対応するパーミッションはそれぞれ以下のようになります。

- 読出し (read) (r) パーミッションはディレクトリー内容リストを可能にします。

- 書込み (write) (w) パーミッションはディレクトリーへのファイルの追加削除を可能にします。

- 実行 (execute) (x) パーミッションはディレクトリー内のファイルへのアクセスを可能にします。

ここで、ディレクトリーに関する実行 (execute) パーミッションとはディレクトリー内のファイルへの読出しを許可するのみならず、サイズや変更時間のようなアトリビュート閲覧を許可します。

ファイルやディレクトリーのパーミッション情報他を表示するには、`ls`(1) が使われます。"`-l`" オプション付きでこれが起動されると、以下の情報がこの順序で表示されます。

- ファイルのタイプ (最初の文字)

- ファイルのアクセスパーミッション (以下の9文字。ユーザーとグループと第三者の順にそれぞれに対して3文字から構成されている)

- ファイルへのハードリンク数

- ファイルを所有するユーザー (user) の名前

- ファイルが所属するグループ (group)

- ファイルのサイズ (文字数、バイト)

- ファイルの日時 (mtime)

- ファイルの名前

表1.4 "`ls -l`" の出力の最初の文字のリスト

文字 | 意味
--- | ---
`-` | 通常ファイル
`d` | ディレクトリー
`l` | シムリンク
`c` | 文字デバイス名
`b` | ブロックデバイス名
`p` | 名前付きパイプ
`s` | ソケット

root アカウントから `chown`(1) を使用することでファイルの所有者を変更します。ファイルの所有者又は root アカウントから `chgrp`(1) を使用することでファイルのグループを変更します。ファイルの所有者又は root アカウントから `chmod`(1) を使用することでファイルやディレクトリーのアクセスパーミッションを変更します。`foo` ファイルの操作の基本的文法は以下の通り。

    # chown newowner foo
    # chgrp newgroup foo
    # chmod  [ugoa][+-=][rwxXst][,...] foo

例えば以下のようにするとディレクトリーツリーの所有者をユーザー `foo` に変更しグループ `bar` で共有できます。

    # cd /some/location/
    # chown -R foo:bar .
    # chmod -R ug+rwX,o=rX .

更に特殊なパーミッションビットが3つ存在します。

- セットユーザー ID ビット (ユーザーの x に代えて s か S)

- セットグループ ID ビット (グループの x に代えて s か S)

- スティッキービット (第三者の x に代えて t か T)

ここで、これらのビットの "`ls -l`" のアウトプットはこれらの出力によってかくされた実行ビットが非設定 (unset) の場合大文字となります。

セットユーザー ID を実行ファイルにセットすると、ユーザーはファイルの所有者 ID (例えば、root) を使って実行ファイルを実行することを許可されます。同様に、セットグループ ID を実行ファイルにセットすると、ユーザーはファイルのグループ ID (例えば、root) を使って実行ファイルを実行することを許可されます。これらの設定はセキュリティーを破壊するリスクを引き起こすので、これらのビットを有効にするには特別な注意が必要です。

セットグループ ID をディレクトリーに対して設定すると、 BSD 的ファイル作成手法が有効になり、ディレクトリーに作成した全ファイルが所属するグループがディレクトリーのものになります。

スティッキビットをディレクトリーに対して有効にすると、ディレクトリーにあるファイルがファイルの所有者以外から削除されるのを防ぎます。"`/tmp`" のような全員書込み可能ディレクトリーやグループ書込み可能なディレクトリーなどのにあるファイルの内容を安全にするためには、書込みパーミッションを無効にするだけでなく、ディレクトリーにスティッキビットもセットする必要があります。さもなければ、ディレクトリーに書込みアクセスできるユーザーにより、ファイルが削除され、同じ名前で新規ファイルが作成されることを許してしまいます。

ファイルパーミッションの興味ある例を次にいくつか示します。

    $ ls -l /etc/passwd /etc/shadow /dev/ppp /usr/sbin/exim4
    crw------T 1 root root   108, 0 Oct 16 20:57 /dev/ppp
    -rw-r--r-- 1 root root     2761 Aug 30 10:38 /etc/passwd
    -rw-r----- 1 root shadow   1695 Aug 30 10:38 /etc/shadow
    -rwsr-xr-x 1 root root   973824 Sep 23 20:04 /usr/sbin/exim4
    $ ls -ld /tmp /var/tmp /usr/local /var/mail /usr/src
    drwxrwxrwt 14 root root  20480 Oct 16 21:25 /tmp
    drwxrwsr-x 10 root staff  4096 Sep 29 22:50 /usr/local
    drwxr-xr-x 10 root root   4096 Oct 11 00:28 /usr/src
    drwxrwsr-x  2 root mail   4096 Oct 15 21:40 /var/mail
    drwxrwxrwt  3 root root   4096 Oct 16 21:20 /var/tmp

`chmod`(1) を用いて、ファイルパーミッションを記述するためのもう一つの数字モードが存在します。この数字モードは8進数を使った3桁から4桁の数字を用います。

表1.5 `chmod`(1) コマンドで用いられるファイルパーミッションの数字モード

数字 | 意味
--- | ---
1桁目 (任意) | セットユーザー ID (=4) とセットグループ ID (=2) とスティキービット (=1) の和
2桁目 | ユーザーに関する、読出し (read) (=4) と書込み (write) (=2) と実行 (execute) (=1) のファイルパーミッションの和
3桁目 | グループに関して、同上
4桁目 | 第三者に関して、同上

これは複雑に聞こえるかもしれませんが、実際は本当にシンプルです。"`ls -l`" コマンドの出力の最初の数列 (2〜10列) を見て、それをファイルパーミッションのバイナリー表記 (2進数) ("-" を "0"、"rwx" を "1") として読むと、この数字モードの値はファイルパーミッションの8進数表現として意味を持ちます。

例えば、次を試してみて下さい:

    $ touch foo bar
    $ chmod u=rw,go=r foo
    $ chmod 644 bar
    $ ls -l foo bar
    -rw-r--r-- 1 penguin penguin 0 Oct 16 21:39 bar
    -rw-r--r-- 1 penguin penguin 0 Oct 16 21:35 foo

| ヒント
シェルスクリプトから "`ls -l`" で表示される情報にアクセスする必要がある際には、`test`(1) や `stat`(1) や `readlink`(1) のような適切なコマンドの使用を考えるべきです。シェル組込みコマンドの "`[`" や "`test`" を使うのも手です。

### 1.2.4. 新規作成ファイルのパーミッションのコントロール: umask

新規作成ファイルのやディレクトリーに適用されるパーミッションは `umask` シェル組込みコマンドを使うことにより制限できます。`dash`(1) か `bash`(1) か `builtins`(7) をご覧下さい。

     (file permissions) = (requested file permissions) & ~(umask value)

表1.6 umask 値の例

umask | 作成されるファイルパーミッション | 作成されるディレクトリーパーミッション | 使い方
--- | --- | --- | ---
`0022` | `-rw-r--r--` | `-rwxr-xr-x` | ユーザーのみにより書込み可
`0002` | `-rw-rw-r--` | `-rwxrwxr-x` | グループにより書込み可

Debian システムはユーザー専用グループ (UPG) 方式をデフォルトで使用します。新規ユーザーがシステムに追加される毎に UPG は作成されます。UPG はそのグループを作成したユーザーと同じ名前を持ち、そのユーザーが UPG の唯一のメンバーです。UPG 方式では全ユーザーが各自専用のグループを持つので、umask を `0002` に設定しても安全です。(一部 Unix 系システムでは全一般ユーザーを1つの `users` グループに所属させることがよく行われます。そのような場合には安全のため umask を`0022` に設定した方がよいでしょう。)

| ヒント
`~/.bashrc` ファイル中に "`umask 002`" と書いて UPG を有効にしましょう。

### 1.2.5. ユーザーのグループ (group) のパーミッション

| 警告
リブートやそれに類する行為をする前に未保存の変更を保存しましょう。

ユーザー `penguin` をグループ `bird` に2ステップで追加できます:

- 以下のいずれか一つでグループ設定を変更します。

  - "`sudo usermod -aG bird penguin`" を実行します。

  - "`sudo adduser penguin bird`" を実行します。(典型的 Debian システム上のみ)

  - `/etc/group` に "`sudo vigr`" を、`/etc/gshadow` に "`sudo vigr -s`" を実行し `bird` の行に `penguin` を追記します。

- 以下のいずれか一つを使い設定を適用します。

  - コールドリブートとログイン。(最適選択肢)

  - GUI メニュー経由でのログアウト。(現代的デスクトップ環境下では、上手く行かないかもしれません。)

ユーザー `penguin` をグループ `bird` から2ステップで削除できます:

- 以下のいずれか一つでグループ設定を変更します。

  - "`sudo usermod -rG bird penguin`" を実行します。

  - "`sudo deluser penguin bird`" を実行します。(典型的 Debian システム上のみ)

  - `/etc/group` に "`sudo vigr`" を、`/etc/gshadow` に "`sudo vigr -s`" を実行し `bird` の行の `penguin` を削除します。

- 以下のいずれか一つを使い設定を適用します。

  - コールドリブートとログイン。(最適選択肢)

  - "`kill -TERM -1`" を実行し、"`systemctl restart NetworkManager.service`" 等のような何らかの修正操作をします。

  - GUI 経由でのログアウトは Gnome Desktop では選択肢ではありません。

現代的なデスクトップ環境では、何らかのワームリブートをしようとしても本物のコールドリブートの脆弱な代用品にしかなりません。

| 注記
もし "`auth optional pam_group.so`" 行が "`/etc/pam.d/common-auth`" に書き加えれ、"`/etc/security/group.conf`" に対応する設定がされていれば、実際のユーザーのグループメンバーシップは動的に割り当てられます。(4章認証とアクセスの制御を参照下さい。)

ハードウエアーデバイスは Debian システム上では一種のファイルでしかありません。USB フラッシュドライブ や CD-ROM のようなデバイスをユーザーアカウントからアクセスするのに問題があった場合にはそのユーザーを該当するグループのメンバーにします。

いくつかのシステムが供給するグループはそのメンバーに `root` 権限無しに特定のファイルやデバイスにアクセスすることを可能にします。

表1.7 ファイルアクセスのためにシステムが供給する特記すべきグループのリスト

グループ | アクセスできるファイルやデバイスの説明
--- | ---
`dialout` | シリアルポート ("`/dev/ttyS[0-3]`") への全面的かつ直接のアクセス
`dip` | 信頼できるピアーにダイヤルアップ IP 接続をするためのシリアルポートへの制限付きアクセス
`cdrom` | CD-ROM や DVD+/-RW のドライバー
`audio` | 音声デバイス
`video` | 映像デバイス
`scanner` | スキャナー
`adm` | システムモニターのログ
`staff` | 下級管理業務のためのディレクトリー: "`/usr/local`"、"`/home`"

| ヒント
モデムの設定をしたりどこにでも電話したり等するには `dialout` グループに所属する必要があります。もし信頼できるピアーに関する事前定義された設定ファイル "`/etc/ppp/peers/`" が `root` によって作られていると、`dip` グループに属するだけで `pppd`(8) や `pon`(1) や `poff`(1) コマンドを用いてダイヤルアップ IP 接続が作成できます。

いくつかのシステムが供給するグループはそのメンバーに `root` 権限無しに特定のコマンドを実行することを可能にします。

表1.8 特定コマンド実行のためにシステムが供給する特記すべきグループのリスト

グループ | 実行可能なコマンド
--- | ---
`sudo` | いかなるコマンドでもスーパーユーザー特権下で実行
`lpadmin` | プリンターのデーターベースからプリンターを追加や変更や削除するコマンドを実行

システムが供給するユーザーやグループの完全なリストは、`base-passwd` パッケージが供給する "`/usr/share/doc/base-passwd/users-and-groups.html`" の中にある最新バージョンの "Users and Groups" 文書を参照下さい。

ユーザーやグループシステムを管理するコマンドは `passwd`(5) や `group`(5) や `shadow`(5) や `newgrp`(1) や `vipw`(8) や `vigr`(8) や `pam_group`(8) を参照下さい。

### 1.2.6. タイムスタンプ

GNU/Linux ファイルのタイムスタンプには3種類あります。

表1.9 タイムスタンプのタイプのリスト

タイプ | 意味 (歴史的 Unix 定義)
--- | ---
mtime | ファイル内容変更時間 (`ls -l`)
ctime | ファイル状態変更時間 (`ls -lc`)
atime | ファイル最終アクセス時間 (`ls -lu`)

| 注記
ctime はファイル作成日時ではありません。

| 注記
GNU/Linux システム上では、実際の atime 値は歴史的 Unix 定義とは異なる場合があります。

- ファイルが上書きされると、ファイルの mtime と ctime と atime の属性すべてが変更されます。

- ファイルの所有者やパーミッションの変更をすると、ファイルの ctime や atime アトリビュートを変えます。

- 伝統的 Unix システム上ではファイルを読むとファイルの atime 属性が変更されます。

- GNU/Linux システム上では、"`strictatime`" でファイルシステムをマウントした場合にファイルを読むとファイルの atime が変更されます。

- ファイルを初めて読み込んだときか、1日空けてアクセスした場合、 ファイルの atime 属性の更新がGNU/Linux (Linux 2.6.30以降) の `relatime` でマウントされているファイルシステムでは生じます。

- atime 属性は `noatime` でマウントされているファイルシステムでは、読み込み時に更新されることはありません。

| 注記
"`noatime`" や "`relatime`" マウントオプションは普通使用状況下でのファイルシステムの読み出しパーフォーマンスを向上させるために導入されました。"`strictatime`" オプション下の単純なファイル読み出しオペレーションは atime 属性を更新する時間のかかる書き込み操作を引き起こします。しかし、 atime 属性は `mbox`(5) ファイルを除くとほとんど使われることはありません。`mount`(8) を参照下さい。

既存ファイルのタイムスタンプを変更するには `touch`(1) コマンドを使って下さい。

タイムスタンプに関して、 `ls` コマンドは非英語ロケール ("`fr_FR.UTF-8`") でローカライズされた文字列を表示します。

    $ LANG=C  ls -l foo
    -rw-rw-r-- 1 penguin penguin 0 Oct 16 21:35 foo
    $ LANG=en_US.UTF-8  ls -l foo
    -rw-rw-r-- 1 penguin penguin 0 Oct 16 21:35 foo
    $ LANG=fr_FR.UTF-8  ls -l foo
    -rw-rw-r-- 1 penguin penguin 0 oct. 16 21:35 foo

| ヒント
"`ls -l`" の出力のカスタム化は「時間と日付のカスタム化表示」を参照下さい。

### 1.2.7. リンク

"`foo`" というファイルを異なるファイル名 "`bar`" に結びつけるのには2つの方法があります。

- ハードリンク

  - 既存ファイルの重複名

  - "`ln foo bar`"

- シンボリックリンクもしくはシムリンク

  - 他のファイルをその名前で指す特殊ファイル

  - "`ln -s foo bar`"

リンク数の変化と `rm` コマンドの結果の微妙な違いについての以下の例をご覧下さい。

    $ umask 002
    $ echo "Original Content" > foo
    $ ls -li foo
    1449840 -rw-rw-r-- 1 penguin penguin 17 Oct 16 21:42 foo
    $ ln foo bar     # hard link
    $ ln -s foo baz  # symlink
    $ ls -li foo bar baz
    1449840 -rw-rw-r-- 2 penguin penguin 17 Oct 16 21:42 bar
    1450180 lrwxrwxrwx 1 penguin penguin  3 Oct 16 21:47 baz -> foo
    1449840 -rw-rw-r-- 2 penguin penguin 17 Oct 16 21:42 foo
    $ rm foo
    $ echo "New Content" > foo
    $ ls -li foo bar baz
    1449840 -rw-rw-r-- 1 penguin penguin 17 Oct 16 21:42 bar
    1450180 lrwxrwxrwx 1 penguin penguin  3 Oct 16 21:47 baz -> foo
    1450183 -rw-rw-r-- 1 penguin penguin 12 Oct 16 21:48 foo
    $ cat bar
    Original Content
    $ cat baz
    New Content

ハードリンクは同一ファイルシステム内に作ることができ、`ls`(1) コマンドに "`-i`" オプションを使って表示される inode 番号が同じです。

シンボリックリンクは上の例に示したように、常にファイルアクセスパーミッション "`rwxrwxrwx`" を持ちますので、シンボリックリンクが指すファイルのアクセスパーミッションが有効ファイルアクセスパーミッションとなります。

| 注意
もし特段の理由がないなら複雑なシンボリックリンクやハードリンクを作らない方が一般的には良いでしょう。シンボリックリンクの論理的組み合わせがファイルシステム中でループになっているという悪夢を引き起こすかもしれません。

| 注記
もしハードリンクを使う特段の理由がなければ、ハードリンクよりシンボリックリンクを使う方が一般的には良いでしょう。

"`.`" ディレクトリーは、それ自身が中にあるディレクトリーとリンクしていますので、新規ディレクトリーのリンク数は2から始まります。"`..`" ディレクトリーは親ディレクトリーとリンクしているので、ディレクトリーのリンク数は新規サブディレクトリーの増加に伴い増加します。

もし最近あなたが Windows から Linux に移動してきたなら、Unix のファイル名のリンクは Windows 上でもっとも似ている "shortcuts" との比較で如何にうまくできているかにすぐ気づくでしょう。ファイルシステム中に実装されているのでアプリケーションからはリンクされたファイルなのかオリジナルなのかの区別がつきません。ハードリンクの場合は実際全く違いはありません。

### 1.2.8. 名前付きパイプ (FIFO)

名前付きパイプは、パイプのように働くファイルです。何かをファイルに入れると、もう一方の端からそれが出てきます。こうしてこれは FIFO または First-In-First-Out (先入れ先出し) と呼ばれます。つまり、最初にパイプに入れられたものが最初にもう一方の端から出てきます。

名前付きパイプに書き込む場合、パイプに書き込むプロセスは情報がパイプから読出されるまで終了しません。名前付きパイプから読み出す場合、読出すプロセス何か読出すものが無くなるまで終了するのを待ちます。パイプのサイズは常に 0 です。 --- 名前付きパイプはデーターを保存せず、 シェルの "`|`" というシンタクッスが提供する機能ように2つのプロセスをリンクするだけです。しかし、このパイプは名前を持つので、2つのプロセスは同じコマンドラインになくても良いし、同じユーザーにより実行される必要さえありません。パイプは Unix の非常に影響力ある発明でした。

例えば、次を試してみて下さい:

    $ cd; mkfifo mypipe
    $ echo "hello" >mypipe & # put into background
    [1] 8022
    $ ls -l mypipe
    prw-rw-r-- 1 penguin penguin 0 Oct 16 21:49 mypipe
    $ cat mypipe
    hello
    [1]+  Done                    echo "hello" >mypipe
    $ ls mypipe
    mypipe
    $ rm mypipe

### 1.2.9. ソケット

ソケットはインターネットのコミュニケーションやデーターベースやオペレーティングシステム自身によって頻繁に使われます。ソケットは名前つきパイプ (FIFO) に似ており、異なるコンピューター間でさえプロセス間の情報交換を可能にします。ソケットにとって、これらのプロセスは同時に実行する必要も、同じ祖先プロセスの子供として実行する必要もありません。これはプロセス間通信 (IPC) の終端点です。ネットワーク越しで異なるホストの間で情報の交換をすることも可能です。2つの典型的なソケットは、インターネットソケットと Unix ドメインソケットです。

| ヒント
"`netstat -an`" を実行すると特定のシステム上のソケットの全般状況がよく分かります。

### 1.2.10. デバイスファイル

デバイスファイルは、システム上のハードディスク、ビデオカード、ディスプレー、キーボードなどの物理デバイス又は仮想デバイス等を意味します。仮想デバイスの例として "`/dev/console`" として表されるコンソールがあります。

2タイプのデバイスファイルがあります。

- 文字デバイス

  - 1文字毎にアクセス可能

  - 1文字 = 1 バイト

  - 例: キーボードデバイス、シリアルポート等

- ブロックデバイス

  - 比較的大きなブロック単位でアクセス可能

  - 1 ブロック > 1 バイト

  - 例: ハードディスク等

デバイスファイルの読出しと書込みは可能ですが、おそらく人間にとっては意味不明のバイナリーデーターがファイル中に含まれています。このようなファイルにデータ書き込むことは、ハードウェアの接続に関するトラブルシューティングに役立つことがあります。例えば、プリンタデバイス "`/dev/lp0`" にテキストファイルをダンプしたり、 適切なシリアルポート "`/dev/ttyS0`" にモデムコマンドを送ることができます。しかし、注意深くやらないと、大災害をもたらすことがあります。くれぐれも気をつけて下さい。

| 注記
普通のプリンターへのアクセスは `lp`(1) を使います。

以下のように `ls`(1) を実行するとデバイスノード番号が表示されます。

    $ ls -l /dev/sda /dev/sr0 /dev/ttyS0 /dev/zero
    brw-rw---T  1 root disk     8,  0 Oct 16 20:57 /dev/sda
    brw-rw---T+ 1 root cdrom   11,  0 Oct 16 21:53 /dev/sr0
    crw-rw---T  1 root dialout  4, 64 Oct 16 20:57 /dev/ttyS0
    crw-rw-rw-  1 root root     1,  5 Oct 16 20:57 /dev/zero

- "`/dev/sda`" はメジャーデバイス番号8 とマイナーデバイス番号0 を持ちます。これは `disk` グループに所属するユーザーにより、読出し / 書込みアクセスが可能です。

- "`/dev/sr0`" はメジャーデバイス番号11 とマイナーデバイス番号0 を持ちます。これは `cdrom` グループに所属するユーザーにより、読出し / 書込みアクセスが可能です。

- "`/dev/ttyS0`" はメジャーデバイス番号4 とマイナーデバイス番号64 を持ちます。これは `dialout` グループに所属するユーザーにより、読出し / 書込みアクセスが可能です。

- "`/dev/zero`" はメジャーデバイス番号1 とマイナーデバイス番号5 を持ちます。これは誰によっても読出し / 書込みアクセスが可能です。

現代的な Linux システムでは、"`/dev/`" の下のファイルは `udev`(7) メカニズムで自動的に充足されます。

### 1.2.11. 特別なデバイスファイル

いくつかの特別なデバイスファイルがあります。

表1.10 スペシャルなデバイスファイルのリスト

デバイスファイル | アクション | レスポンスの説明
--- | --- | ---
`/dev/null` | 読出し | "行末 (EOF) 文字 " を返す
`/dev/null` | 書込み | 何も返さず (底なしのデーターのゴミ捨て場)
`/dev/zero` | 読出し | "`\0` (NUL) 文字" を返す (ASCII の数字のゼロとは違う)
`/dev/random` | 読出し | 真の乱数発生機から真のエントロピーのあるランダムな文字を返す (遅い)
`/dev/urandom` | 読出し | 暗号学的にセキュアーな擬似乱数発生機からランダムな文字を返す
`/dev/full` | 書込み | ディスクフル (ENOSPC) エラーを返す

以上はシェルのリディレクションとともによく使われます。(「典型的なコマンドシーケンスとシェルリディレクション」を参照下さい)。

### 1.2.12. procfs と sysfs

procfs と sysfs は "`/proc`" や "`/sys`" 上にマウントされる仮想ファイルシステムであり、カーネルの内部データー構造をユーザー空間にさらけ出します。言い換えると、オペレーティングシステムのオペレーションへの便利なのぞき窓となると言う意味で仮想といえます。

"`/proc`" ディレクトリー中には、システム上で実行されている各プロセスに対応したそのプロセス ID (PID) の名前がついたサブディレクトリー他があります。プロセス情報をアクセスする `ps`(1) のようなシステムユーティリティーはこのディレクトリー構造からその情報を得ています。

"`/proc/sys/`" の下のディレクトリーには実行時のカーネル変数を変更するインターフェースがあります。(専用の `sysctl`(8) コマンドもしくはそのプリロード / 設定ファイル "`/etc/sysctl.conf`" によっても同様のことができます。)

特にあるファイル - "`/proc/kcore`" - に気づくと、パニックになる人がよくいます。これは一般に巨大です。これは (おおよそ) コンピューターのメモリーの内容のコピーです。これは kernel をデバッグするのに用いられます。コンピューターのメモリーを指す仮想ファイルなので、そのサイズに関して心配する必要は全くありません。

"`/sys`" の下のディレクトリーはカーネルから引き出されたデーター構造、その属性、それらの関連を含んでいます。一部カーネル変数を実行時に変更する機構もまた含まれたりします。

`linux-doc-*` パッケージで供給される Linux カーネル文書 ("`/usr/share/doc/linux-doc-2.6.*/Documentation/filesystems/*`") 中の "`proc.txt(.gz)`" や "`sysfs.txt(.gz)`" や関連する他の文書を参照下さい。

### 1.2.13. tmpfs

tmpfs は 仮想記憶 中にすべてのファイルを保持する一時的なファイルシステムです。メモリー上のページキャッシュ中にある tmpfs のデーターは必要に応じてディスク上の swap 空間 へと書き出せます。

"`/run`" ディレクトリは初期ブートプロセスに tmpfs としてマウントされます。こうすることで "`/`" が読み取り専用でマウントされていてもそこへの書き込みが可能です。これは過渡的な状態ファイルの保管のための新たな場所で、Filesystem Hierarchy Standard のバージョン 2.3に規定されたいくつかの場所を置き換えます:

- "`/var/run`" → "`/run`"

- "`/var/lock`" → "`/run/lock`"

- "`/dev/shm`" → "`/run/shm`"

`linux-doc-*` パッケージで供給される Linux カーネル文書 ("`/usr/share/doc/linux-doc-*/Documentation/filesystems/*`") 中の "`tmpfs.txt(.gz)`" を参照下さい。

## 1.3. ミッドナイトコマンダー (MC)

Midnight Commander (MC) は Linux コンソールや他の端末環境のための GNU 製 "スイス軍ナイフ" です。標準 Unix コマンドを習うよりもより簡単なメニューを使ったコンソール経験が初心者にもできます。

"`mc`" と名づけられた Midnight Commander パッケージを以下のようにしてインストールする必要があります。

    $ sudo apt-get install mc

Debian システムを探検するために `mc`(1) コマンドを使います。これは学習するための最良の方法です。カーソールキーとエンターキーを使うだけで興味深い場所をちょっと探検します。

- "`/etc`" とサブディレクトリー

- "`/var/log`" とサブディレクトリー

- "`/usr/share/doc`" とサブディレクトリー

- "`/usr/sbin`" と "`/usr/bin`"。

### 1.3.1. MC のカスタム化

終了時に作業ディレクトリーを MC に変更させそのディレクトリーへ `cd` させるためには、`mc` パッケージが提供するスクリプトを "`~/.bashrc`" が含むように変更します。

    . /usr/lib/mc/mc.sh

この理由は `mc`(1) ("`-P`" オプション項目) を参照下さい (今言っていることがよく分からないなら、これは後日しても大丈夫です。)

### 1.3.2. MC の始動

MC は以下のようにして起動します。

    $ mc

MC を使うとメニューを通じた最小限のユーザーの努力で全てのファイル操作の面倒が見られます。ヘルプ表示を出すには、ただ F1 を押すだけです。カーソールキーとファンクションキーの操作だけで MC を使えます。

| 注記
`gnome-terminal`(1) のようなコンソールでは、ファンクションキーのキーストロークがコンソールプログラムに横取りされる事があります。`gnome-terminal` の場合、"Preferences" → "General" や "Shortcuts" メニューからこの機能を無効にできます。

もし文字化け表示がされる文字符号化 (エンコーディング) 問題に出会った際には、MC のコマンドラインに "`-a`" を加えると解消する事があります。

これでも MC の表示の問題が解消しない際には、「ターミナルの設定」を参照下さい。

### 1.3.3. MC のファイルマネージャー

2つのディレクトリーパネルがありそれぞれファイルリストを含むのが標準です。他の便利なモードとしては、右側のウィンドウを "information" とセットしてファイルアクセス権情報などを表示するモードがあります。次にいくつかの不可欠なキーストロークを示します。`gpm`(8) デーモンを実行すると、Linux の文字ターミナルでマウスも使えます。(MC で普通の挙動のカットアンドペーストをさせるには、shift キーを押して下さい。)

表1.11 MC のキーバインディング

キー | キーバインディング
--- | ---
`F1` | ヘルプメニュー
`F3` | 内部ファイルビューワー
`F4` | 内部エディター
`F9` | プルダウンメニュー有効
`F10` | MC を終了
`Tab` | 二つのウィンドウの間を移動
`Insert` もしくは `Ctrl-T` | コピーのような複数ファイル操作のためにファイルをマーク
`Del` | ファイルの削除 (気をつけましょう -- MC を安全削除モードに設定)
カーソールキー | 自明

### 1.3.4. MC のコマンドライントリック

- `cd` コマンドは選択されたスクリーンに表示されたディレクトリーを変更します。

- `Ctrl-Enter` と `Alt-Enter` はファイル名をコマンドラインにコピーします。コマンドライン編集と一緒に `cp`(1) や `mv`(1) コマンドで御使用下さい。

- `Alt-Tab` はシェルファイル名の自動展開の選択肢を表示します。

- MC の引数で両ウィンドウのスタートディレクトリーを指定できます。例えば "`mc /etc /root`"。

- `Esc` + `n-key` → `Fn` (つまり、`Esc` + `1` → `F1`、等々、`Esc` + `0` → `F10`)

- `Esc` をキーの前に押すのは `Alt` をキーと同時に押すのと同様の効果があります。つまり、`Esc` + `c` は `Alt-C` と同じです。`Esc` はメタキーとよばれ時々 "`M-`" と表記されます。

### 1.3.5. MC の内部エディター

MC の内部エディターは興味深いカットアンドペースト機構を持ちます。`F3` キーを押すと、選択範囲のスタートとマークし、次に `F3` を押すと、選択範囲のエンドとマークし、選択範囲を強調します。そしてカーソールを動かすことができます。F6 を押すと、選択範囲はカーソールの位置に移動します。F5 を押すと、選択範囲はコピーされ、カーソールの位置に挿入されます。`F2` を押すとファイルを保存します。`F10` を押すと選択範囲はなくなります。ほとんどのカーソールキーは直感的に働きます。

このエディターは以下のコマンドの内のひとつを使いファイルに対し直接起動できます。

    $ mc -e filename_to_edit

    $ mcedit filename_to_edit

これはマルチモードエディターではありませんが、複数の Linux コンソール上で使用すると同じ効果を発揮させされます。ウィンドウ間のコピーを行うには、 Alt-n キーを押して仮想コンソールを切替えて、"File→Insert file" や "File→Copy to file" を用いてファイルの一部を他のファイルに動かします。

この内部エディターはお好きな他の外部エディターと置き換えが可能です。

また、多くのプログラムは使用するエディターを決定するために環境変数 "`$EDITOR`" や "`$VISUAL`" を使用します。最初 `vim`(1) や `nano`(1) が使いにくい場合には "`~/.bashrc`" に次に示す行を追加してエディターを "`mcedit`" に設定するのも一計です。

    export EDITOR=mcedit
    export VISUAL=mcedit

できればこれは "`vim`" に設定することを推奨します。

`vim`(1) が使いにくい場合には、`mcedit`(1) をほとんどのシステム管理業務のために使い続けられます。

### 1.3.6. MC の内部ビューワー

MC は非常に賢明なビューワーです。文書内の単語を検索するための素晴らしいツールです。私は "`/usr/share/doc`" ディレクトリー内のファイルに対していつもこれを使います。これは 大量にある Linux 情報を閲覧する最速の方法です。このビューワーは以下のコマンドの内のひとつを使い直接起動できます。

    $ mc -v path/to/filename_to_view

    $ mcview path/to/filename_to_view

### 1.3.7. MC の自動起動機能

ファイルの上で Enter を押すと、適切なプログラムがファイル内容を処理します (「スタートするプログラムのカスタム化」を参照下さい)。これは非常に便利な MC の機能です。

表1.12 enter キー入力への MC の反応

ファイルタイプ | enter キーへの反応
--- | ---
実行ファイル | コマンド実行
man ファイル | ビューワーソフトに内容をパイプ
html ファイル | ウェッブブラウザーに内容をパイプ
"`*.tar.gz`" や "`*.deb`" ファイル | サブディレクトリーであるかのように内容を表示

これらのビューワーや仮想ファイルの機能を有効にするためには、閲覧可能なファイルには実行可能と設定されていてはいけません。`chmod`(1) コマンドを使うか、MC のファイルメニュー経由で状態を変更して下さい。

### 1.3.8. MC の仮想ファイルシステム

MC は Internet 経由でのファイルアクセスに使えます。`F9` を押してメニューに行き、"`Enter`" と "`h`" を押して仮想ファイルシステムをアクティベートします。"`sh://[user@]machine[:options]/[remote-dir]`" の形式で URL を入力すると、`ssh` を利用してあたかもローカルにあるかのようにリモートディレクトリーを取得します。

## 1.4. 基本の Unix 的作業環境

MC はほとんど全てのことを可能にしますが、シェルプロンプトから起動されるコマンドラインツールの使用方法について学び、Unix 的な作業環境に親しむのは非常に重要なことです。

### 1.4.1. login シェル

login シェルはシステム初期化プログラムによって使われることがあるので、`bash`(1) のままにし、`chsh`(1) を使って login シェルを切り替えることを避けることが賢明です。

もし異なるインタラクティブなシェルプロンプトを使いたい場合には、GUI ターミナル エミュレーターのコンフィギュレーションからの設定や、例えば "`exec /usr/bin/zsh -i -l`" や "`exec /usr/bin/fish -i -l`" 等と書き込んだ `~/.bashrc` から起動しましょう。

表1.13 シェルプログラムのリスト

パッケージ | ポプコン | サイズ | POSIX シェル | 説明
--- | --- | --- | --- | ---
`bash` | V:866, I:999 | 7277 | はい | Bash: GNU Bourne Again SHell (デファクトスタンダード)
`bash-completion` | V:35, I:953 | 1952 | N/A | bash シェルのプログラム可能なコンプリーション
`dash` | V:906, I:998 | 207 | はい | Debian の Almquist シェル、シェルスクリプトに好適
`zsh` | V:40, I:70 | 2509 | はい | Z shell: 多くの拡張された標準シェル
`tcsh` | V:4, I:15 | 1366 | いいえ | TENEX C Shell: 拡張バージョンの Berkeley csh
`mksh` | V:5, I:8 | 7713 | はい | Korn シェル の１バージョン
`csh` | V:1, I:5 | 348 | いいえ | OpenBSD の C シェル、Berkeley csh の派生
`sash` | V:0, I:5 | 1335 | はい | 組み込みコマンド付きの独立シェル (標準の "`/usr/bin/sh`" には不向き)
`ksh` | I:8 | 65 | はい | 真の AT&T バージョンの Korn シェル
`rc` | V:0, I:0 | 182 | いいえ | AT&T Plan 9 の rc シェルの実装
`posh` | V:0, I:0 | 187 | はい | ポリシー準拠の通常のシェル (`pdksh` の派生)

| ヒント
POSIX-ライクなシェルは基本シンタックスはにていますが、シェル変数や glob の展開のような基本事項の挙動が異なることがあります。詳細に関しては個々の文書を確認して下さい。

このチュートリアル章内では、インタラクティブなシェルは常に `bash` です。

### 1.4.2. Bash のカスタム化

`vim`(1) の挙動は "`~/.vimrc`" を使ってカスタム化できます。

例えば、次を試してみて下さい。

    # enable bash-completion
    if ! shopt -oq posix; then
      if [ -f /usr/share/bash-completion/bash_completion ]; then
        . /usr/share/bash-completion/bash_completion
      elif [ -f /etc/bash_completion ]; then
        . /etc/bash_completion
      fi
    fi

    # CD upon exiting MC
    . /usr/lib/mc/mc.sh

    # set CDPATH to a good one
    CDPATH=.:/usr/share/doc:~:~/Desktop:~
    export CDPATH

    PATH="${PATH+$PATH:}/usr/sbin:/sbin"
    # set PATH so it includes user's private bin if it exists
    if [ -d ~/bin ] ; then
      PATH="~/bin${PATH+:$PATH}"
    fi
    export PATH

    EDITOR=vim
    export EDITOR

| ヒント
`bash` に関する更なるカスタム化方法は、9章システムに関するティップ中の「着色化されたコマンド」等にあります。

| ヒント
`bash-completion` パッケージは `bash` で入力のプログラムによる補完を可能にします。

### 1.4.3. 特別のキーストローク

Unix 的環境下では、特別の意味を持ったいくつかのキーストロークがあります。普通の Linux の文字ターミナルでは左側の `Ctrl` や `Alt` キーのみが期待にそって機能することを承知下さい。次に特記すべき暗記するべきキーストロークを記します。

表1.14 Bash のキーバインディングのリスト

キー | キーバインディングの説明
--- | ---
`Ctrl-U` | カーソールの前の1行を消去
`Ctrl-H` | カーソールの前の1文字を削除
`Ctrl-D` | 入力を終了 (シェルを使用中の場合、シェルを終了)
`Ctrl-C` | 実行中のプログラムを終了
`Ctrl-Z` | プログラムをバックグラウンドジョブに移動し一時停止
`Ctrl-S` | スクリーンへの出力を停止
`Ctrl-Q` | スクリーンへの出力を再開
`Ctrl-Alt-Del` | システムをリブート / 停止、`inittab`(5) 参照下さい
`Left-Alt キー` (もしくは、`Windows キー`) | Emacs および同様の UI でのメタキー
`Up-arrow` | `bash` でコマンド履歴検索をスタート
`Ctrl-R` | `bash` でインクリメンタルなコマンド履歴検索をスタート
`Tab` | `bash` のコマンドラインのファイル名入力を完結
`Ctrl-V` `Tab` | `bash` のコマンドラインで `Tab` を展開することなく入力

| ヒント
ターミナルの `Ctrl-S` 機能は `stty`(1) で無効にできます。

### 1.4.4. マウス操作

Debian システム上の文字列へのマウス操作は 2 つのスタイルを混ぜていて少々複雑です:

- 伝統的な Unix 流のマウス操作:

  - 3 ボタンの使用 (クリック)

  - プライマリーを使用

  - `xterm` のような X アプリケーションや Linux コンソール中のテキストアプリケーションが使用

- 現代的な GUI 流のマウス操作:

  - 2 ボタンの使用 (ドラッグ + クリック)

  - プライマリーとクリップボードを使用

  - `gnome-terminal` のような現代的な GUI アプリケーションが使用

表1.15 Debian 上でのマウス操作と関連キー操作のリスト

アクション | 反応
--- | ---
マウスの左クリックアンドドラッグ | プライマリーの選択範囲の選択
左クリック | プライマリーの選択スタート点の選択
右クリック（伝統的） | プライマリーの選択エンド点の選択
右クリック（現代的） | コンテキスト依存のメニュー (カット/コピー/ペースト)
ミドルクリックまたは Shift-`Ins` | プライマリーの選択をカーソール位置に挿入
`Ctrl-X` | プライマリーの選択をクリップボードにカット
`Ctrl-C` (ターミナルで `Shift-Ctrl-C`) | プライマリーの選択をクリップボードにコピー
`Ctrl-V` | クリップボードをカーソール位置に挿入(ペースト)

ここで、プライマリーの選択はハイライトされたテキスト範囲です。実行中プログラムの停止を避けるため、ターミナルプログラム内では `Shift-Ctrl-C` が代用で使われています。

現代的なホイールマウスの真ん中のホイールは中マウスボタンと見なされ、中クリックに使えます。2ボタンマウス状況では左右のボタンの同時押しが中クリックとして使えます。

Linux 文字コンソールでマウスを使うには `gpm`(8) をデーモンで実行する必要があります。

### 1.4.5. ページャー

`less`(1) は機能拡張されたページャー (ファイル内容のブラウザー) です。コマンドアーギュメントに指定されたファイル、もしくは標準入力を読みます`less`。コマンドで閲覧中にヘルプが必要なら、"`h`" を押しましょう。これは、`more`(1) よりもはるかに高機能で、"`eval $(lesspipe)`" または "`eval $(lessfile)`" をシェルのスタートスクリプト中で実行することで更に機能が拡充されます。詳しくは、"`/usr/share/doc/less/LESSOPEN`" を参照下さい。"`-R`" オプションを用いると、生の文字出力やANSI カラーエスケープシーケンスが有効になります。`less`(1) を参照下さい。

| ヒント
`less` コマンドでは、ヘルプスクリーンを見るには "`h`" とタイプし、文字列検索をするには "`/`" か "`?`" とタイプし、大文字と小文字の区別・非区別を変更するには "`-i`" とタイプします。

### 1.4.6. テキストエディター

Unix 的システムで人気のある、Vim か Emacs プログラムのいずれかのバリアントに習熟するべきです。

著者としては Vim コマンドに慣れることは正しいことだと考えています。なぜなら Vi エディターは Linux/Unix の世界では必ず存在するからです。(実際はオリジナルの `vi` か、新しい `nvi` がどこででも見つけられるプログラムです。これにもかかわらず Vim を著者が初心者のために選んだのは、より強力かつ動作が充分似ているのと、`F1` キーを通じてヘルプが表示されるからです。)

これとは違い、Emacs か XEmacs をエディターとして選ぶのも、特にプログラムをするには、非常に良い選択です。Emacs には、ニュースリーダ機能、ディレクトリーの編集機能、メール機能他の、過多な機能があります。プログラミングやシェルスクリプトの編集に使うときは、作業中のフォーマットをインテリジェントに認識し助力をしようとします。Linux 上で必要なプログラムは Emacs だけと考える人もいます。Emacs を今10分間学ぶことは将来何時間もの節約になります。Emacs を学ぶ際には GNU の Emacs マニュアルを持っておくことを高く推薦します。

これら全てのプログラムには練習しながら学べるようにチュータリングプログラムが通常同梱されています。Vim を "`vim`" とタイプして起動し、F1 キーを押します。最初の35行を読みます。カーソールを "`|tutor|`" に移動し `Ctrl-]` を押してオンラインの訓練コースを始めます。

| 注記
Vim や Emacs のような良いエディターは、UTF-8 や他のエギゾチックな符号化方式 (エンコーディング) のテキストを正しく扱えます。それにはUTF-8ロケール中のGUI環境で、必要なプログラムとフォントをインストールをするのが賢明です。エディタにはGUI環境に依らずにファイルのエンコーディングを設定するオプションがあります。マルチバイトテキストについてはそれぞれの文書を参照下さい。

### 1.4.7. デフォールトのテキストエディターの設定

Debian にはいくつかの異なったエディターがあります。上述のように `vim` パッケージをインストールすることを推薦します。

Debian ではシステムのデフォールトのエディターへの統一されたアクセスを "`/usr/bin/editor`" コマンドを通じて提供しているので、他のプログラム (例えば `reportbug`(1) 等) がエディターを起動できます。設定変更は次で出来ます。

    $ sudo update-alternatives --config editor

著者が "`/usr/bin/vim.tiny`" より "`/usr/bin/vim.basic`" を初心者に推薦するのはシンタクスハイライトをサポートしているからです。

| ヒント
多くのプログラムは "`$EDITOR`" か "`$VISUAL`" という環境変数を使ってどのエディターを使うかを決めます (「MC の内部エディター」と「スタートするプログラムのカスタム化」を参照下さい)。Debian システムの整合性のために、これらを "`/usr/bin/editor`" と設定しましょう。(歴史的には "`$EDITOR`" は "`ed`" で、"`$VISUAL`" は "`vi`" でした。)

### 1.4.8. Vim 利用法

最近の `vim`(1) は合理的な "`nocompatible`" モードで起動し `NORMAL` モードに入ります。[1]

表1.16 基本の Vim キーストロークのリスト

モード | キーストローク | アクション
--- | --- | ---
`NORMAL` | `:help|only` | ヘルプファイルを表示します
`NORMAL` | `:e filename.ext` | `filename.ext` を編集するために新規バッファーを開きます
`NORMAL` | `:w` | 現バッファーを元ファイルに上書きします
`NORMAL` | `:w filename.ext` | 現バッファーを `filename.ext` に書きます
`NORMAL` | `:q` | `vim` を終了します
`NORMAL` | `q!` | `vim` を強制終了します
`NORMAL` | `:only` | 分割し開かれているすべての他ウィンドウを閉じます
`NORMAL` | `:set nocompatible?` | `vim` が合理的な `nocompatible` モードかを確認します
`NORMAL` | `:set nocompatible` | `vim` が合理的な `nocompatible` モードに設定します
`NORMAL` | `i` | `INSERT` モードに入ります
`NORMAL` | `R` | `REPLACE` モードに入ります
`NORMAL` | `v` | `VISUAL` モードに入ります
`NORMAL` | `V` | 行単位の `VISUAL` モードに入ります
`NORMAL` | Ctrl-`V` | ブロック単位の `VISUAL` モードに入ります
`TERMINAL-JOB` 以外 | `ESC`-キー | `NORMAL` モードに入ります
`NORMAL` | `:term` | `TERMINAL-JOB` モードに入ります
`TERMINAL-NORMAL` | `i` | `TERMINAL-JOB` モードに入ります
`TERMINAL-JOB` | Ctrl-`W` `N` (もしくは Ctrl-`\` Ctrl-`N`) | `TERMINAL-NORMAL` モードに入ります
`TERMINAL-JOB` | Ctrl-`W` `:` | `TERMINAL-NORMAL` 中の `Ex`モードに入ります

`vim` をインタラクティブなチュートリアルコースで学習する"`vimtutor`" プログラムを使いましょう。

`vim` プログラムは モード に基づきタイプされたキーストロークへの挙動を変えます。 バッファーにキーストロークをタイプ入力するのは `INSERT` モードと `REPLACE` モード主にされます。カーソール移動は `NORMAL` モードで主にされます。インタラクティブな選択は `VISUAL` モードでされます。`NORMAL` モードで "`:`" をタイプするとそのモード が `Ex` モードに代わります。`Ex` モードはコマンドを受け付けます。

| ヒント
Vim には Netrw パッケージが同梱されています。Netrw はファイルの読み書きやディレクトリーのネットワーク経由やローカルの閲覧を可能にします！Netrw を "`vim .`" (アーギュメントとしてピリオド) として試し、"`:help netrw`" にあるマニュアルを読みましょう。

`vim` の高度な設定は、「Vim のカスタム化」を参照下さい。

### 1.4.9. シェル活動の記録

シェルコマンドの出力はスクリーンから押し出されると永久に無くなってしまうかもしれません。シェルでの活動を後で見直せるようにファイルに記録しておくのは良いことです。この種の記録は何らかのシステム管理作業をする際には非常に重要です。

| ヒント
新しい Vim (version>=8.2) は `TERMINAL-JOB` モードを使うときれいにシェル活動を記録できます。「Vim 利用法」を参照下さい。

シェル活動の記録の基本方法は `script`(1) の下で実行することです。

例えば、次を試してみて下さい:

    $ script
    Script started, file is typescript

`script` の下で何なりのシェルコマンドを実行します。

`Ctrl-D` を押して `script` から脱出します。

    $ vim typescript

「シェルの活動を綺麗に記録」を参照下さい。

### 1.4.10. 基本 Unix コマンド

基本的 Unix コマンドを学びます。ここでは一般的意味で "Unix" を使っています。いかなる Unix クローンの OS も通常等価なコマンドを提供します。Debian システムも例外ではありません。今一部コマンドが思うように機能しなくても心配しないで下さい。`エイリアス`がシェルで使われた場合は、対応するコマンドの出力は変わります。次は順番に実行すると言う意味の例ではありません。

非特権ユーザーのアカウントから以下のコマンドを全て実行します。

表1.17 基本の Unix コマンドのリスト

コマンド | 説明
--- | ---
`pwd` | カレント / ワーキングディレクトリーの名前を表示
`whoami` | 現在のユーザー名を表示
`id` | 現在のユーザーのアイデンティティ (名前と uid と gid と関連する group) を表示
`file foo` | "`foo`" ファイルのファイルタイプを表示
`type -p commandname` | "`commandname`" コマンドのファイルの位置を表示
`which commandname` | , ,
`type commandname` | "`commandname`" コマンドに関する情報を表示
`apropos key-word` | "`key-word`" に関連したコマンドを発見
`man -k key-word` | , ,
`whatis commandname` | "`commandname`" コマンドに関する1行の説明を表示
`man -a commandname` | "`commandname`" コマンドに関する説明を表示 (Unix スタイル)
`info commandname` | "`commandname`" コマンドに関する比較的長い説明を表示 (GNU スタイル)
`ls` | ディレクトリーの内容をリスト (非ドットファイルおよびディレクトリー)
`ls -a` | ディレクトリーの内容をリスト (全ファイルおよびディレクトリー)
`ls -A` | ディレクトリーの内容をリスト (ほとんど全ファイルおよびディレクトリー、"`..`" と "`.`" をスキップ)
`ls -la` | ディレクトリーの内容を詳細情報とともにリスト
`ls -lai` | ディレクトリーの内容を inode 番号と詳細情報とともにリスト
`ls -d` | 現ディレクトリーの中の全ディレクトリーをリスト
`tree` | ファイルツリーの内容を表示
`lsof foo` | "`foo`" ファイルのオープンの状態をリスト
`lsof -p pid` | プロセス ID: "`pid`" によってオープンされたファイルをリスト
`mkdir foo` | 現ディレクトリー中に "`foo`" という新規ディレクトリー作成
`rmdir foo` | 現ディレクトリー中の "`foo`" というディレクトリーを削除
`cd foo` | 現ディレクトリー中もしくは "`$CDPATH`" 変数中にリストされたディレクトリー中の "`foo`" というディレクトリーにディレクトリーを変更
`cd /` | ディレクトリーをルートディレクトリーに変更
`cd` | 現在のユーザーのホームディレクトリーにディレクトリーを変更
`cd /foo` | 絶対ディレクトリーパス "`/foo`" にディレクトリーを変更
`cd ..` | 親ディレクトリーにディレクトリーを変更
`cd ~foo` | ユーザー "`foo`" のホームディレクトリーにディレクトリーを変更
`cd -` | 一つ前のディレクトリーにディレクトリーを変更
`</etc/motd pager` | "`/etc/motd`" の内容をデフォールトのページャーで表示
`touch junkfile` | 空ファイル "`junkfile`" を作成
`cp foo bar` | 既存のファイル "`foo`" を新規ファイル "`bar`" にコピー
`rm junkfile` | ファイル "`junkfile`" を削除
`mv foo bar` | 既存のファイル "`foo`" の名前を新しい名前 "`bar`" に変更 (ディレクトリー "`bar`" が存在不可)
`mv foo bar` | 既存のファイル "`foo`" を新しい場所 "`bar/foo`" に移動 (ディレクトリー "`bar`" が存在しなければいけない)
`mv foo bar/baz` | 既存のファイル "`foo`" を新しい場所の新しい名前のファイル "`bar/baz`" に移動 (ディレクトリー "`bar`" が存在しなければいけないが、ディレクトリー "`bar/baz`" は存在してはいけない)
`chmod 600 foo` | 既存のファイル "`foo`" を第三者から読出し不可かつ書込み不可 (全員実行不可)
`chmod 644 foo` | 既存のファイル "`foo`" を第三者からは読出し可だが書込み不可 (全員実行不可)
`chmod 755 foo` | 既存のファイル "`foo`" を第三者からは読出し可だが書込み不可 (全員実行可能)
`find . -name pattern` | シェルで "`pattern`" にマッチするファイル名を探索 (比較的遅い)
`locate -d . pattern` | シェルで "`pattern`" にマッチするファイル名を探索 (定期的に生成されるデーターベースを使い比較的早い)
`grep -e "pattern" *.html` | 現ディレクトリーにある "`.html`" で終わる全ファイルから "`pattern`" のパターンを検索し、該当する全ファイルを表示
`top` | フルスクリーンを用いてプロセス情報を表示し、"`q`" と押して終了
`ps aux | pager` | 実行中の全プロセスの情報を BSD スタイルの出力を用いて表示
`ps -ef | pager` | 実行中の全プロセスの情報を System-V スタイルの出力を用いて表示
`ps aux | grep -e "[e]xim4*"` | "`exim`" もしくは "`exim4`" の実行中の全プロセスを表示
`ps axf | pager` | 実行中の全プロセスの情報を ASCII アート出力を用いて表示
`kill 1234` | プロセス ID"1234" により識別されるプロセスを停止
`gzip foo` | Lempel-Ziv コーディング (LZ77) を用いて "`foo`" を圧縮し "`foo.gz`" を作成
`gunzip foo.gz` | "`foo.gz`" を解凍して "`foo`" を作成
`bzip2 foo` | Burrows-Wheeler ブロックソートテキスト圧縮アルゴリズムと Huffman コーディングを用いて "`foo`" を圧縮し "`foo.bz2`" を作成 (`gzip` より高圧縮率)
`bunzip2 foo.bz2` | "`foo.bz2`" を解凍して "`foo`" を作成
`xz foo` | Lempel–Ziv–Markov鎖アルゴリズムを用いて "`foo`" を圧縮し "`foo.xz`" を作成 (`bzip2` より高圧縮率)
`unxz foo.xz` | "`foo.xz`" を解凍して "`foo`" を作成
`tar -xvf foo.tar` | "`foo.tar`" アーカイブからファイルを展開
`tar -xvzf foo.tar.gz` | gzip 圧縮された "`foo.tar.gz`" アーカイブからファイルを展開
`tar -xvjf foo.tar.bz2` | "`foo.tar.bz2`" アーカイブからファイルを展開
`tar -xvJf foo.tar.xz` | "`foo.tar.xz`" アーカイブからファイルを展開
`tar -cvf foo.tar bar/` | フォルダ "`bar/`" の内容を "`foo.tar`" アーカイブにアーカイブ
`tar -cvzf foo.tar.gz bar/` | フォルダ "`bar/`" の内容を "`foo.tar.gz`" アーカイブに圧縮アーカイブ
`tar -cvjf foo.tar.bz2 bar/` | フォルダ "`bar/`" の内容を "`foo.tar.bz2`" アーカイブに圧縮アーカイブ
`tar -cvJf foo.tar.xz bar/` | フォルダ "`bar/`" の内容を "`foo.tar.xz`" アーカイブに圧縮アーカイブ
`zcat README.gz | pager` | 圧縮された "`README.gz`" の内容をデフォルトのページャーを用いて表示
`zcat README.gz > foo` | "`README.gz`" の内容を解凍してファイル "`foo`" を作成
`zcat README.gz >> foo` | 展開された "`README.gz`" の内容をファイル "`foo`" の末尾に追加 (ファイルが存在しない場合は事前に作成)

| 注記

Unix は "`.`" で始まるファイル名を隠す伝統があります。それらは伝統的には特定の設定情報やユーザーの嗜好を含むファイルです。

`cd` コマンドに関しては `builtins`(7) を参照下さい。

最小限の Debian システムではデフォルトのページャーが `more`(1) で、スクロールバックができません。`less` パッケージを "`apt-get install less`" というコマンドラインでインストールすると、`less`(1) が デフォルトのページャーになりカーソールキーでスクロールバック出来るようになります。

上記の "`ps aux | grep -e "[e]xim4*"`" コマンド中に現れる正規表現中の "`[`" と "`]`" によって `grep` が自分自身にマッチするのを避けることができます。正規表現中の "`4*`" は数字 "`4`" の0回以上の繰り返しを意味するので、`grep` が "`exim`" と "`exim4`" の両方にマッチします。 "`*`" はシェルのファイルネームのグロブと正規表現で使われますが、意味が違います。`grep`(1) から正規表現を学びましょう。

上記のコマンドを訓練として用いて、ディレクトリーを渡り歩き、システムの中を覗き込んで下さい。コンソールのコマンドに関して質問がある場合は、必ずマニュアルページを読んでみて下さい。

例えば、次を試してみて下さい:

    $ man man
    $ man bash
    $ man builtins
    $ man grep
    $ man ls

マンページのスタイルは慣れるのに少々大変かもしれません。なぜなら特に比較的旧式の非常に伝統的なマンページは比較的言葉が少ないからです。しかし一旦慣れるとその簡潔さの良さが分かるでしょう。

GNU や BSD 由来を含む多くの Unix 的なコマンドは以下のように (場合によっては一切の引数無しで) 起動すると簡単なヘルプ情報を表示することを承知下さい。

    $ commandname --help
    $ commandname -h

## 1.5. シェルプロンプト

Debian システムの使い方が少し分かったでしょう。Debian システム上でのコマンド実行のメカニズムを掘り下げます。初心者のためにちょっと簡略化してみました。正確な説明は `bash`(1) を参照下さい。

シンプルなコマンドは、以下の要素のシーケンスとなります。

1. 変数代入 (任意)

2. コマンド名

3. 引数 (任意)

4. リダイレクト (任意: `>` と `>>` と `<` と `<<` 等。)

5. 制御演算子 (任意: `&&` と `||` と 改行 と `;` と `&` と `(` と `)`)

### 1.5.1. コマンド実行と環境変数

環境変数の値は Unix コマンドの挙動を変えます。

環境変数のデフォールト値は PAM システムが初期設定されます。その後以下のような何らかのアプリケーションプログラムにより再設定されているかもしれません。

- `pam_env` のような PAM システム は `/etc/pam.conf`" や "`/etc/environment`" や "`/etc/default/locale`" によって環境変数を設定できます。

- `gdm3` のようなディスプレーマネージャーはGUIセッション向けの環境変数を "`~/.profile`" を使って再設定します。

- ユーザー特定のプログラム初期化は "`~/.profile`" や "`~/.bash_profile`" や "`~/.bashrc`" により環境変数を再設定することがあります。

### 1.5.2. "`$LANG`" 変数

デフォルトのロケールは "`$LANG`" 環境変数中に定義され、インストーラーか、GNOME の場合なら "Settings" → "Region & Language" → "Language" / "Formats" と言ったその後の GUI 設定によって "`LANG=xx_YY.UTF-8`" 等と設定されます。

| 注記
本当に必要な場合でなければ、"`$LC_*`" 変数を避け、とりあえず "`$LANG`" 変数のみを用いてシステム環境を設定する事をお薦めします。

"`$LANG`" 変数に与えられる完全なロケール値は3つの部分からなります: "`xx_YY.ZZZZ`"。

表1.18 ロケールの値の3つの部分

ロケールの値 | 意味
--- | ---
`xx` | ISO 639 言語コード (小文字)、例えば "en"
`YY` | ISO 3166 国コード (大文字)、例えば "US"
`ZZZZ` | コードセット、常に "UTF-8" と設定

表1.19 推奨ロケールのリスト

推奨ロケール | 言語 (地域)
--- | ---
`en_US.UTF-8` | 英語 (米国)
`en_GB.UTF-8` | 英語 (英国)
`fr_FR.UTF-8` | フランス語 (フランス)
`de_DE.UTF-8` | ドイツ語 (ドイツ)
`it_IT.UTF-8` | イタリア語 (イタリア)
`es_ES.UTF-8` | スペイン語 (スペイン)
`ca_ES.UTF-8` | カタラン語 (スペイン)
`sv_SE.UTF-8` | スウェーデン語 (スウェーデン)
`pt_BR.UTF-8` | ポルトガル語 (ブラジル)
`ru_RU.UTF-8` | ロシア語 (ロシア)
`zh_CN.UTF-8` | 中国語 (中華人民共和国)
`zh_TW.UTF-8` | 中国語 (台湾 R.O.C.)
`ja_JP.UTF-8` | 日本語 (日本)
`ko_KR.UTF-8` | 韓国語 (大韓民国)
`vi_VN.UTF-8` | ベトナム語 (ベトナム)

典型的なコマンドの実行は以下のようなシェルの行シーケンスを用います。

    $ echo $LANG
    en_US.UTF-8
    $ date -u
    Wed 19 May 2021 03:18:43 PM UTC
    $ LANG=fr_FR.UTF-8 date -u
    mer. 19 mai 2021 15:19:02 UTC

以上で、`date`(1) プログラムは異なるロケール変数で実行されます。

- 最初のコマンドでは、"`$LANG`" はシステムのデフォルトのロケール値 "`en_US.UTF-8`" に設定されます。

- 二番目のコマンドでは、"`$LANG`" はフランス語の UTF-8 ロケール値 "`fr_FR.UTF-8`" に設定されます。

ほとんどのコマンド実行は通常頭に環境変数定義をつけません。上記の例の代わりに以下のように実行します。

    $ LANG=fr_FR.UTF-8
    $ date -u
    mer. 19 mai 2021 15:19:24 UTC

| ヒント
バグを報告する場合、もし非英語環境を使っているならば、プログラムを "`en_US.UTF-8`" ロケールの下で実行し確認することが望ましいです。

ロケールの詳細に関しては、「ロケール」を参照下さい。

### 1.5.3. "`$PATH`" 変数

シェルにコマンドを打ち込んだ際に、シェルは "`$PATH`" 環境変数にリストされたディレクトリーのリストから検索します。"`$PATH`" 環境変数の値は、シェルの検索パスとも呼ばれます。

標準の Debian インストールでは、ユーザーアカウントの "`$PATH`" 環境変数には "`/usr/sbin`" や "`/usr/sbin`" が含まれないかもしれません。例えば、`ifconfig` コマンドは "`/usr/sbin/ifconfig`" とフルパスを使って実行する必要があります。(類似の `ip` コマンドは "`/usr/bin`" にあります。)

Bash シェルの "`$PATH`" 環境変数は、"`~/.bash_profile`" か "`~/.bashrc`" ファイルで変更できます。

### 1.5.4. "`$HOME`" 変数

多くのコマンドはユーザー特定の設定をホームディレクトリーに保存し、その内容でコマンドの挙動が変わります。ホームディレクトリーは "`$HOME`" 環境変数で指定されます。

表1.20 "`$HOME`" の値のリスト

"`$HOME`" の値 | プログラム実行状況
--- | ---
`/` | init プロセスが実行するプログラム (デーモン)
`/root` | 普通の root シェルから実行されるプログラム
`/home/normal_user` | 普通のユーザーシェルから実行されるプログラム
`/home/normal_user` | 普通のユーザーの GUI デスクトップメニューから実行されるプログラム
`/home/normal_user` | "`sudo program`" を用いて root として実行されるプログラム
`/root` | "`sudo -H program`" を用いて root として実行されるプログラム

| ヒント
シェルは、"`~/`" を現ユーザーのホームディレクトリーである "`$HOME/`" へと展開します。シェルは、"`~foo/`" をユーザー `foo` のホームディレクトリーである "`/home/foo/`" へと展開します。

もし `$HOME` をあなたのプログラムから使えない場合には、「シェル環境変数」を参照下さい。

### 1.5.5. コマンドラインオプション

プログラムコマンドによっては引数があります。引数は "`-`" か "`--`" で始まり、オプションと呼ばれ、コマンドの挙動をコントロールします。

    $ date
    Thu 20 May 2021 01:08:08 AM JST
    $ date -R
    Thu, 20 May 2021 01:08:12 +0900

上記で、コマンドライン引数 "`-R`" が `date`(1) の挙動を RFC2822 準拠の日付文字列出力と変えています。

### 1.5.6. シェルグロブ

ファイル名を全てタイプせずにファイルのグループをコマンド処理したいことがよくあります。シェルのグロブ (ワイルドカードとも時々呼ばれる) を用いたファイル名のパターン展開を用いるとこのニーズに答えられます。

表1.21 シェルグロブパターン

シェルグロブパターン | マッチルールの説明
--- | ---
`*` | "`.`" で始まらないファイル (部分) 名
`.*` | "`.`" で始まるファイル (部分) 名
`?` | 1文字
`[…]` | 括弧中の1文字
`[a-z]` | "`a`" と "`z`" の範囲間の1文字
`[^…]` | 括弧内 ("`^`" 以外) に含まれる文字以外の1文字

例えば、次を試してみて下さい:

    $ mkdir junk; cd junk; touch 1.txt 2.txt 3.c 4.h .5.txt ..6.txt
    $ echo *.txt
    1.txt 2.txt
    $ echo *
    1.txt 2.txt 3.c 4.h
    $ echo *.[hc]
    3.c 4.h
    $ echo .*
    . .. .5.txt ..6.txt
    $ echo .*[^.]*
    .5.txt ..6.txt
    $ echo [^1-3]*
    4.h
    $ cd ..; rm -rf junk

`glob`(7) を参照下さい。

| 注記
普通のシェルのファイル名の展開と違い、`find`(1) が "`-name`" テスト他でシェルパターン "`*`" をテストする際にはファイル名先頭の "`.`" ともマッチします。(新 POSIX 機能)

| 注記
BASH は shopt 組み込みオプションで "`dotglob`" や "`noglob`" や "`nocaseglob`" や "`nullglob`" や "`extglob`" などとすることでグロブ挙動を色々変更できます。`bash`(1) を参照下さい。

### 1.5.7. コマンドの戻り値

各コマンドは終了ステータスを戻り値 (変数: "`$?`") として返します。

表1.22 コマンドの終了コード

コマンドの終了状態 | 戻り値の数値 | 戻り値の論理値
--- | --- | ---
成功 | ゼロ、0 | 真
失敗 | 非ゼロ、-1 | 偽

例えば、次を試してみて下さい。

    $ [ 1 = 1 ] ; echo $?
    0
    $ [ 1 = 2 ] ; echo $?
    1

| 注記
シェルの論理的な観点では、成功は、0 (ゼロ) の値を持つ論理的真として扱われることを承知下さい。少々これは非直感的なのでここで再確認する必要があります。

### 1.5.8. 典型的なコマンドシーケンスとシェルリディレクション

次に挙げるシェルコマンドの一部として一行でタイプするシェルコマンドの慣用句を覚えましょう。

表1.23 シェルコマンドの慣用句

コマンドの慣用句 | 説明
--- | ---
`command &` | `command` をサブシェル中でバックグラウンド実行
`command1 | command2` | `command1` の標準出力を `command2` の標準入力に パイプ (同時並行で実行)
`command1 2>&1 | command2` | `command1` の標準出力と標準エラー出力を `command2` の標準入力にパイプ (同時進行で実行)
`command1 ; command2` | `command1` を実行し、後に続いて `command2` を実行
`command1 && command2` | `command1` を実行; もし成功したら、 後に続いて `command2` を実行 (`command1` と `command2` の両方が成功したら、正常終了を返す)
`command1 || command2` | `command1` を実行; もし成功しなかったら、後に続いて `command2` を実行 (`command1` か `command2` のどちらかが成功したら、正常終了を返す)
`command > foo` | `command` の標準出力を `foo` ファイルにリダイレクト (上書き)
`command 2> foo` | `command` の標準エラー出力をファイル `foo` にリダイレクト (上書き)
`command >> foo` | `command` の標準出力をファイル `foo` にリダイレクト (追記)
`command 2>> foo` | `command` の標準エラー出力を `foo` ファイルにリダイレクト (追記)
`command > foo 2>&1` | `command` の標準出力と標準エラー出力を `foo` ファイルにリダイレクト
`command < foo` | `command` の標準入力を `foo` ファイルからリダイレクト
`command << delimiter` | `command` の標準入力を "`delimiter`" に出会うまでのこれに続く行からリダイレクト (ヒアドキュメント)
`command <<- delimiter` | `command` の標準入力を "`delimiter`" に出会うまでのこれに続く行からリダイレクト (ヒアドキュメント、行頭のタブ文字は入力から削除)

Debian システムはマルチタスクシステムです。バックグラウンドジョブを使うと単一シェルの下で複数プログラムを実行可能にします。バックグラウンドジョブの管理にはシェル内部組み込みコマンドの `jobs` や `fg` や `bg` や `kill` を使います。bash(1) マンページ中の "SIGNALS" と "JOB CONTROL" セクションや `builtins`(1) を参照下さい。

例えば、次を試してみて下さい:

    $ </etc/motd pager

    $ pager </etc/motd

    $ pager /etc/motd

    $ cat /etc/motd | pager

4つ全ての例が全く同じ表示をしますが、最後の例は余計な `cat` コマンドを実行するので理由なくリソースを無駄に遣います。

シェルでは `exec` 組み込みコマンドを任意のファイルディスクリプタとともに使いファイルをオープンすることができます。

    $ echo Hello >foo
    $ exec 3<foo 4>bar  # open files
    $ cat <&3 >&4       # redirect stdin to 3, stdout to 4
    $ exec 3<&- 4>&-    # close files
    $ cat bar
    Hello

ファイルデスクリプタの 0-2 は事前定義されています。

表1.24 事前定義されたファイルデスクリプタ

デバイス | 説明 | ファイルデスクリプタ
--- | --- | ---
`stdin` | 標準出力 | 0
`stdout` | 標準出力 | 1
`stderr` | 標準エラー出力 | 2

### 1.5.9. コマンドエイリアス

良く使うコマンドにエイリアスを設定できます。

例えば、次を試してみて下さい:

    $ alias la='ls -la'

こうすると、"`la`" が "`ls -la`" の短縮形として機能し、全てのファイルを長いリスト形式でリストします。

既存のエイリアスは `alias` でリストできます (`bash`(1) の "SHELL BUILTIN COMMANDS" 参照下さい)。

    $ alias
    ...
    alias la='ls -la'

`type` 内部コマンドを使うと正確なパスやコマンドの正体を識別できます (`bash`(1) の "SHELL BUILTIN COMMANDS" 下参照下さい)。

例えば、次を試してみて下さい:

    $ type ls
    ls is hashed (/bin/ls)
    $ type la
    la is aliased to ls -la
    $ type echo
    echo is a shell builtin
    $ type file
    file is /usr/bin/file

上記で、`ls` は最近探索されましたが "`file`" は最近探索されていませので、"`ls`" は "ハッシュされた" つまりシェルには "`ls`" コマンドの場所を高速アクセスのために内部記録していると表示されます。

| ヒント
「着色化されたコマンド」を参照下さい。

## 1.6. Unix 的テキスト処理

Unix 的作業環境では、テキスト処理はテキストを標準テキスト処理ツールの連鎖パイプを通す行います。これは決定的な Unix の発明です。

### 1.6.1. Unix テキストツール

Unix 的システムでしばしば使われる標準テキスト処理ツールがいくつかあります。

- 正規表現を使わないもの:

  - `cat`(1) はファイルをつなぎ合わせて内容を全て出力します。

  - `tac`(1) はファイルをつなぎ合わせ逆順で出力します。

  - `cut`(1) は行の一部を選択し出力します。

  - `head`(1) はファイルの最初の部分を選択し出力します。

  - `tail`(1) はファイルの最後の部分を選択し出力します。

  - `sort`(1) は行を順番に並び替えます。

  - `uniq`(1) は順番に並べられたファイルから重複行を削除します。

  - `tr`(1) は文字を変換削除します。

  - `diff`(1) は1行ごとにファイルを比較します。

- 基本正規表現 (BRE) をデフォルトで使用するもの:

  - `ed`(1) は原始的な行エディターです。

  - `sed`(1) はストリームエディターです。

  - `egrep`(1) はテキストのパターンマッチをします。

  - `vim`(1) はスクリーンエディターです。

  - `emacs`(1) はスクリーンエディターです。(ちょっと拡張された BRE)

- 拡張正規表現 (ERE) を使用するもの:

  - `awk`(1) は単純なテキスト処理をします。

  - `egrep`(1) はテキストのパターンマッチをします。

  - `tcl`(3tcl) は考え得る全てのテキスト処理をします: `re_syntax`(3)。時々 `tk`(3tk) とともに使用されます。

  - `perl`(1) は考え得る全てのテキスト処理をします。`perlre`(1).

  - `pcre2-util` パッケージの `pcre2grep`(1) はテキストのパターンマッチを Perl 互換正規表現 (PCRE) パターンを使ってします。

  - `re` モジュールとともに使うことで `python`(1) は考え得る全てのテキスト処理をします。"`/usr/share/doc/python/html/index.html`" を参照下さい。

もしこれらのコマンドが正確にどう動作するかを確認したいなら、"`man command`" を使って自分で見つけましょう。

| 注記
ソート順や範囲表現はロケールに依存します。コマンドの従来の挙動を得たい場合は、 UTF-8 がついた普通のロケール（「ロケール」を参照）ではなく、C または C.UTF-8 ロケールを使います。

| 注記
Perl 正規表現 (`perlre`(1)) と Perl 互換正規表現 (PCRE) と `re` モジュールで提供される Python 正規表現は ERE に多くの共通の拡張をしています。

### 1.6.2. 正規表現

正規表現は多くのテキスト処理ツールで使われています。シェルグロブに類似していますがより複雑で強力です。

正規表現はマッチするパターンを表現し、テキスト文字とメタ文字からなっています。

メタ文字は特別な意味を持った文字です。上記のようにテキストツールによって、BRE と ERE の2つの主要なスタイルがあります。

表1.25 BRE と ERE のメタ文字

BRE | ERE | 正規表現の説明
--- | --- | ---
`\ . [ ] ^ $ *` | `\ . [ ] ^ $ *` | 共通のメタ文字
`\+ \? \( \) \{ \} \|` |  | "`\`" でエスケープされた、BRE のみで用いるメタ文字
| `+ ? ( ) { } |` | "`\`" でエスケープされ無い、ERE のみで用いるメタ文字
`c` | `c` | 非メタ文字 "`c`" にマッチ
`\c` | `\c` | "`c`" 自身がメタ文字でも "`c`" という文字そのものとマッチ
`.` | `.` | 改行を含む全ての文字とマッチ
`^` | `^` | 文字列の最初
`$` | `$` | 文字列の最後
`\<` | `\<` | 単語の先頭
`\>` | `\>` | 単語の末尾
`[abc…]` | `[abc…]` | "`abc…`" のいずれかの文字にマッチ
`[^abc…]` | `[^abc…]` | "`abc…`" 以外の文字にマッチ
`r*` | `r*` | "`r`" という正規表現の0回以上にマッチ
`r\+` | `r+` | "`r`" という正規表現の1回以上にマッチ
`r\?` | `r?` | "`r`" という正規表現の0回か1回にマッチ
`r1\|r2` | `r1|r2` | "`r1`" か "`r2`" という正規表現のいずれかにマッチ
`\(r1\|r2\)` | `(r1|r2)` | "`r1`" か "`r2`" という正規表現のいずれかにマッチし、それを括弧で囲まれた正規表現と見なす

`emacs` の正規表現は、ERE 同様の "`+`" と "`?`" をメタ文字と扱う拡張をしてはありますが、基本的に BRE です。これら文字を `emacs` の正規表現で "`\`" でエスケープする必要はありません。

`grep`(1) によって正規表現を使った文字列探索ができます。

例えば、次を試してみて下さい:

    $ egrep 'GNU.*LICENSE|Yoyodyne' /usr/share/common-licenses/GPL
    GNU GENERAL PUBLIC LICENSE
    GNU GENERAL PUBLIC LICENSE
    Yoyodyne, Inc., hereby disclaims all copyright interest in the program

| ヒント
「着色化されたコマンド」を参照下さい。

### 1.6.3. 置換式

置換式の場合、一部の文字は特別な意味を持ちます。

表1.26 置換式

置換式 | 置換式を置換する文字の説明
--- | ---
`&` | 正規表現がマッチしたもの (`emacs` では `\&` を使用)
`\n` | n番目の括弧で囲まれた正規表現にマッチしたもの ("n" は数字)

Perl の代替文字列には"&" に代えて "$&" が使われ、 "\n" に代えて "$n" が使われます。

例えば、次を試してみて下さい:

    $ echo zzz1abc2efg3hij4 | \
    sed -e 's/\(1[a-z]*\)[0-9]*\(.*\)$/=&=/'
    zzz=1abc2efg3hij4=
    $ echo zzz1abc2efg3hij4 | \
    sed -E -e 's/(1[a-z]*)[0-9]*(.*)$/=&=/'
    zzz=1abc2efg3hij4=
    $ echo zzz1abc2efg3hij4 | \
    perl -pe 's/(1[a-z]*)[0-9]*(.*)$/=$&=/'
    zzz=1abc2efg3hij4=
    $ echo zzz1abc2efg3hij4 | \
    sed -e 's/\(1[a-z]*\)[0-9]*\(.*\)$/\2===\1/'
    zzzefg3hij4===1abc
    $ echo zzz1abc2efg3hij4 | \
    sed -E -e 's/(1[a-z]*)[0-9]*(.*)$/\2===\1/'
    zzzefg3hij4===1abc
    $ echo zzz1abc2efg3hij4 | \
    perl -pe 's/(1[a-z]*)[0-9]*(.*)$/$2===$1/'
    zzzefg3hij4===1abc

ここで、括弧で囲まれた正規表現のスタイルと、マッチした文字列が異なるツール上でテキスト置換処理にどう使われるかとに注目下さい。

これらの正規表現は一部エディター内でカーソールの動きやテキスト置換アクションに対しても使えます。

シェルコマンドラインの行末のバックスラッシュ "`\`" は改行をホワイトスペース文字としてエスケープするので、シェルコマンドライン入力を次行に継続させます。

これらのコマンドを習うために、関連するマニュアルページを全て読んで下さい。

### 1.6.4. 正規表現を使ったグローバル置換

`ed`(1) コマンドは以下のようにすると "`file`" 中に存在する全ての "`FROM_REGEX`" を "`TO_TEXT`" に置換できます。

    $ ed file <<EOF
    ,s/FROM_REGEX/TO_TEXT/g
    w
    q
    EOF

`sed`(1) コマンドは以下のようにすると "`file`" 中に存在する全ての "`FROM_REGEX`" を "`TO_TEXT`" に置換できます。

    $ sed -i -e 's/FROM_REGEX/TO_TEXT/g' file

`vim`(1) コマンドは `ex`(1) コマンドを使い以下のようにすると "`file`" 中に存在する全ての "`FROM_REGEX`" を "`TO_TEXT`" に置換できます。

    $ vim '+%s/FROM_REGEX/TO_TEXT/gc' '+update' '+q' file

| ヒント
上記の "`c`" フラグをにより各置換毎に対話型の確認をします。

複数ファイル ("`file1`" と "`file2`" と "`file3`") を `vim`(1) や `perl`(1) で同様に正規表現を用いて処理できます。

    $ vim '+argdo %s/FROM_REGEX/TO_TEXT/gce|update' '+q' file1 file2 file3

| ヒント
上記の "`e`" フラグをにより "No match" エラーでマッピングが停止することを防ぎます。

    $ perl -i -p -e 's/FROM_REGEX/TO_TEXT/g;' file1 file2 file3

perl(1) の例中で、"`-i`" はその場で各ターゲットファイルの編集、"`-p`" は与えられたすべてのファイルに関する暗黙的なループを意味します。

| ヒント
"`-i`" の代わりに "`-i.bak`" という引数を用いるとオリジナルファイル名に "`.bak`" をつけたファイル名でオリジナルファイルが保管されます。複雑な置換のエラーからの復元が簡単にできます。

| 注記
`ed`(1) や `vim`(1) は BRE です。一方、`perl`(1) は ERE です。

### 1.6.5. テキストファイルからのデーター抽出

2004年以前の元 Debian リーダの名前と就任日がスペースで分割されたフォーマットでリストされている "`DPL`" と呼ばれるファイルを考えてみましょう。

    Ian     Murdock   August  1993
    Bruce   Perens    April   1996
    Ian     Jackson   January 1998
    Wichert Akkerman  January 1999
    Ben     Collins   April   2001
    Bdale   Garbee    April   2002
    Martin  Michlmayr March   2003

| ヒント
最新のDebian のリーダーの歴史に関しては、"A Brief History of Debian" を参照下さい。

Awk はこういったタイプのファイルからデーターを抽出するために良く使われます。

例えば、次を試してみて下さい:

    $ awk '{ print $3 }' <DPL                   # month started
    August
    April
    January
    January
    April
    April
    March
    $ awk '($1=="Ian") { print }' <DPL          # DPL called Ian
    Ian     Murdock   August  1993
    Ian     Jackson   January 1998
    $ awk '($2=="Perens") { print $3,$4 }' <DPL # When Perens started
    April 1996

Bash などのシェルもこれらのファイルを解釈するのに使えます。

例えば、次を試してみて下さい:

    $ while read first last month year; do
        echo $month
      done <DPL
    ... same output as the first Awk example

ここで、`read` 組込みコマンドは "`$IFS`" (内部フィールドセパレータ) を用いて行を単語単位で分割します。

"`$IFS`" を "`:`" に変更すると、"`/etc/passwd`" をシェルでうまく解読できます。

    $ oldIFS="$IFS"   # save old value
    $ IFS=':'
    $ while read user password uid gid rest_of_line; do
        if [ "$user" = "bozo" ]; then
          echo "$user's ID is $uid"
        fi
      done < /etc/passwd
    bozo's ID is 1000
    $ IFS="$oldIFS"   # restore old value

(同じことを Awk を使って行うには、フィールドセパレータ設定は "`FS=':'`" とします。)

IFS はパラメーター展開、コマンド置換、数式展開の結果を分割するためにもシェルにより使われます。これはダブルクォートやシングルクォートされた単語内では発生しません。IFS の標準値は space と tab と newline の組合せです。

シェルの IFS トリックを注意深く使って下さい。シェルがスクリプトの一部を入力として解釈した場合に、奇妙なことが起きるかもしれません。

    $ IFS=":,"                        # use ":" and "," as IFS
    $ echo IFS=$IFS,   IFS="$IFS"     # echo is a Bash builtin
    IFS=  , IFS=:,
    $ date -R                         # just a command output
    Sat, 23 Aug 2003 08:30:15 +0200
    $ echo $(date -R)                 # sub shell --> input to main shell
    Sat  23 Aug 2003 08 30 36 +0200
    $ unset IFS                       # reset IFS to the default
    $ echo $(date -R)
    Sat, 23 Aug 2003 08:30:50 +0200

### 1.6.6. コマンドをパイプするためのスクリプト断片

以下のスクリプトはパイプの一部として素晴らしいことをします。

表1.27 コマンドをパイプするためのスクリプト断片

スクリプト断片 (1行入力) | コマンドの効果
--- | ---
`find /usr -print` | "`/usr`" の下の全ファイル発見
`seq 1 100` | 1から100までプリント
`| xargs -n 1 command` | パイプからの各項目を引数としてコマンドを反復実行
`| xargs -n 1 echo` | パイプからのホワイトスペースで分離された項目を行に分割
`| xargs echo` | パイプからの全ての行を1行にマージ
`| grep -e regex_pattern` | regex_pattern を含む行を抽出
`| grep -v -e regex_pattern` | regex_pattern を含まない行を抽出
`| cut -d: -f3 -` | "`:`" で区切られた3番目のフィールドを抽出 (passwd ファイルなど)
`| awk '{ print $3 }'` | ホワイトスペースで区切られた3番目のフィールドを抽出
`| awk -F'\t' '{ print $3 }'` | タブで区切られた3番目のフィールドを抽出
`| col -bx` | バックスペースを削除し、タブをスベースに変換
`| expand -` | タブをスベースに変換
`| sort| uniq` | 入力をソートし重複を削除
`| tr 'A-Z' 'a-z'` | 大文字を小文字に変換
`| tr -d '\n'` | 複数行を1行に連結
`| tr -d '\r'` | キャリッジリターンを削除
`| sed 's/^/# /'` | 各行頭に "`#`" を追加
`| sed 's/\.ext//g'` | "`.ext`" を削除
`| sed -n -e 2p` | 2番目の行を表示
`| head -n 2 -` | 最初の2行を表示
`| tail -n 2 -` | 最後の2行を表示

1行のシェルスクリプトは `find`(1) や `xargs`(1) を使って非常に複雑な操作を多くのファイルに繰り返し実行できます。「ファイル選択の慣用句」と「ファイルに関してループしながらコマンドを反復実行」を参照下さい。

シェルの対話モードを使うのが複雑過ぎるようになったときには、シェルのスクリプトを書くのも一計です (「シェルスクリプト」を参照下さい)。

[1] 比較的古い `vim` ですら起動時に"`-N`" オプションをつけることで合理的な "`nocompatible`" モードで起動できます。

序章 |  | 第2章 Debian パッケージ管理