はじめに
この実験では、Linux のコマンドライン環境でファイルやディレクトリを管理するための基本的なスキルを習得します。mkdir や rm を使用して複雑なディレクトリ構造を作成・削除したり、cp や mv を使ってファイルやディレクトリをコピー・移動したりする実戦的な経験を積むことができます。
さらに、この実験ではファイルの「リンク」についても詳しく掘り下げます。ln コマンドを使用してシンボリックリンク(ソフトリンク)とハードリンクの両方を作成し、その背後にある概念である i ノード(inode) を分析します。また、元のファイルが変更されたときに各リンクがどのように振る舞うかを観察します。これにより、Linux ファイルシステムがどのようにデータを整理し、参照しているかについて、より深い理解を得ることができます。
mkdir、rmdir、rm によるディレクトリ構造の作成と削除
このステップでは、ディレクトリの作成と削除の方法を学びます。ファイルを階層的なディレクトリ構造に整理することは、Linux における基本的なタスクです。ディレクトリの作成には mkdir、空のディレクトリの削除には rmdir、ディレクトリとその中身すべての削除には rm コマンドを使用します。すべてのコマンドは、デフォルトのディレクトリである ~/project から実行します。
まず、シンプルなディレクトリを作成してみましょう。mkdir コマンドは「make directory」の略です。
ターミナルで次のコマンドを実行し、cars という名前のディレクトリを作成します。
mkdir cars
ディレクトリが作成されたことを確認するには、ls -ld コマンドを使用します。-l オプションは詳細なリスト形式で表示し、-d オプションはディレクトリの中身ではなく、ディレクトリ自体のエントリを表示します。
ls -ld cars
次のような出力が表示され、cars ディレクトリが作成されたことが確認できるはずです。パーミッション文字列の先頭にある d は、それがディレクトリであることを示しています。
drwxr-xr-x 2 labex labex 4096 May 20 10:30 cars
次に、このディレクトリを削除してみましょう。rmdir コマンドは、空のディレクトリを削除するために使用されます。
rmdir cars
再度 ls -ld コマンドを実行して、削除されたことを確認します。
ls -ld cars
今回は、ディレクトリがもう存在しないため、エラーメッセージが表示されます。これにより、rmdir が成功したことが確認できます。
ls: cannot access 'cars': No such file or directory
rmdir コマンドは空のディレクトリに対してのみ機能します。では、入れ子になったディレクトリ構造がある場合はどうすればよいでしょうか。pastry/pies/cakes というディレクトリ構造を作成してみましょう。必要に応じて親ディレクトリも同時に作成するには、mkdir に -p(parents)オプションを付ける必要があります。
次のコマンドを実行してください。
mkdir -p pastry/pies/cakes
作成したディレクトリ構造全体を確認するには、ls コマンドに -l(詳細形式)と -R(再帰的)オプションを付けて使用します。
ls -lR pastry
出力には、pastry ディレクトリとそのサブディレクトリである pies および cakes が表示されます。
pastry:
total 4
drwxr-xr-x 3 labex labex 4096 May 20 10:35 pies
pastry/pies:
total 4
drwxr-xr-x 2 labex labex 4096 May 20 10:35 cakes
pastry/pies/cakes:
total 0
ここで、rmdir を使って pastry ディレクトリを削除しようとしてみましょう。
rmdir pastry
なぜこのコマンドは失敗したのでしょうか?ターミナルには次のようなエラーメッセージが表示されます。
rmdir: failed to remove 'pastry': Directory not empty
これは、rmdir が空のディレクトリしか削除できず、pastry には pies というサブディレクトリが含まれているためです。
ディレクトリとその中身(サブディレクトリやファイルを含む)をすべて削除するには、rm コマンドに -r(recursive:再帰的)オプションを付けて使用する必要があります。このコマンドはデータを永久に削除する可能性があるため、実行には細心の注意を払ってください。
rm -r pastry
成功した場合、このコマンドは何も出力しません。再度 ls -ld pastry を実行して、「No such file or directory」エラーが出ることを確認すれば、pastry ディレクトリが完全に削除されたことがわかります。
ls -ld pastry
vi と ln -s によるファイルの作成とシンボリックリンク
このステップでは、vi テキストエディタを使用してファイルを作成し、そのファイルへのシンボリックリンクを作成します。シンボリックリンク(symlink またはソフトリンクとも呼ばれます)は、別のファイルやディレクトリを指し示す特殊なファイルです。他のオペレーティングシステムにおける「ショートカット」に似ています。
まず、vi を使って filea という名前のシンプルなテキストファイルを作成しましょう。vi は強力なスクリーン型テキストエディタです。主に「コマンドモード」と「挿入モード」の 2 つのモードがあります。起動時はコマンドモードになっており、キー入力はコマンドとして解釈されます。文字を入力するには、挿入モードに切り替える必要があります。
- ターミナル(パスは
~/projectであるはずです)でviを起動し、fileaを作成します。
vi filea
- ターミナルに
viのエディタ画面が表示されます。入力を開始するには、iキーを 1 回押して挿入モードに切り替えます。画面の下部に-- INSERT --と表示される場合があります。 - 次のテキストを入力します。
This is filea.
- ファイルを保存して
viを終了するには、まずEscキーを押してコマンドモードに戻ります。次に、ZZ(Shift を押しながら Z を 2 回)と入力します。このコマンドはファイルを保存してエディタを終了します。
コマンドプロンプトに戻ったら、ファイルが作成され、正しい内容が含まれているか確認しましょう。
まず、ファイルをリスト表示します。
ls filea
出力はファイル名だけが表示されるはずです。
filea
次に、cat コマンドを使用して内容を表示します。
cat filea
入力したテキストが表示されるはずです。
This is filea.
次に、シンボリックリンクを作成します。元のファイル filea を指す fileb という名前のリンクを作成します。コマンドは ln -s <元ファイル> <リンク名> です。
ln -s filea fileb
結果を確認するために、ls -il コマンドを使用します。-i オプションは i ノード(inode)番号を表示します。これはファイルシステム上のファイルやディレクトリを識別する一意の番号です。
ls -il file[ab]
出力を注意深く確認してください。
131075 -rw-r--r-- 1 labex labex 14 May 20 10:40 filea
131076 lrwxrwxrwx 1 labex labex 5 May 20 10:41 fileb -> filea
いくつかの重要なポイントがあります。
- ファイルタイプ:
fileaのパーミッション文字列は-で始まっており、通常のファイルであることを示しています。一方、filebはlで始まっており、シンボリックリンクであることを示しています。 - リンクのポインタ: 出力には
fileb -> fileaと明確に表示されています。 - i ノード番号: 最初の列を見てください。
fileaとfilebの i ノード番号は異なります。なぜなら、シンボリックリンクはターゲットファイルへのパスを保存しているだけの「別のファイル」だからです。リンク自体が独立したファイルであるため、独自の i ノードを持ちます。
最後に、リンク経由で内容を読み取れるか確認しましょう。
cat fileb
filea の内容が表示されます。
This is filea.
これは期待通りの動作です。シンボリックリンクに対して cat などの操作を行うと、システムは自動的にリンクを辿って元のファイルにアクセスし、操作を実行します。
ln と i ノードによるハードリンクの作成と分析
このステップでは、ハードリンクを作成し、それが前のステップで作成したシンボリックリンクとどのように違うのかを学びます。ファイル名へのポインタであるシンボリックリンクとは異なり、ハードリンクは「ファイルそのものに対する別の名前」です。どちらの名前も、ディスク上の同じデータ(i ノードという一意の番号で識別される)を直接指し示します。
引き続き ~/project ディレクトリにある filea と fileb を使用します。
まず、filea と同じ i ノードを指す filec という名前のハードリンクを作成します。これを行うには、-s オプションを付けずに ln コマンドを使用します。
ln filea filec
ここで、元の filea、シンボリックリンク fileb、そして新しいハードリンク filec の 3 つのファイルすべての内容を確認してみましょう。
cat filea
cat fileb
cat filec
同じ内容が 3 回表示されるはずです。
This is filea.
This is filea.
This is filea.
本当の違いは、ファイルの属性を調べたときに明らかになります。再度 ls -il コマンドを使用して、3 つのファイルの i ノード番号と詳細を表示します。
ls -il file[a-c]
出力は次のようになります。第 1 列と第 2 列に注目してください。
131075 -rw-r--r-- 2 labex labex 14 May 20 10:40 filea
131076 lrwxrwxrwx 1 labex labex 5 May 20 10:41 fileb -> filea
131075 -rw-r--r-- 2 labex labex 14 May 20 10:40 filec
この出力を分析してみましょう。
- i ノード番号(第 1 列):
fileaとfilecが全く同じ i ノード番号(例:131075)を持っていることに注目してください。これがハードリンクの決定的な特徴です。これらは別々のファイルではなく、ディスク上の同一のファイルデータを指す 2 つの異なる名前に過ぎません。一方、シンボリックリンクfilebは独自の i ノードを持っています。 - リンクカウント(第 2 列):
fileaとfilecの数字を見てください。2になっています。この数字はハードリンクカウントと呼ばれ、この 1 つの i ノードを指している名前(ハードリンク)がいくつあるかを追跡しています。filecを作成したことで、この i ノードのリンクカウントが 1 から 2 に増えました。 - ファイルタイプ(パーミッションの 1 文字目):
filecはfileaと同様に通常のファイル(-で始まる)としてリストされています。fileb(lで始まる)のような特殊なリンクタイプではありません。
元ファイルを変更した後のリンクの挙動の観察
このステップでは、元のファイルが削除され、その後に再作成されたときに、シンボリックリンクとハードリンクの挙動にどのような決定的な違いが生じるかを観察します。これにより、各リンクの仕組みについての理解が深まります。引き続き ~/project ディレクトリの filea、fileb、filec を使用します。
まず、元のファイル filea を削除します。
rm filea
次に、3 つのファイルの状態を確認します。ls -l コマンドを使用します。filea はもう存在しないため、エラーが表示されますが、これは想定内です。
ls -l file[a-c]
出力結果から多くのことがわかります。
ls: cannot access 'filea': No such file or directory
lrwxrwxrwx 1 labex labex 5 May 20 10:41 fileb -> filea
-rw-r--r-- 1 labex labex 14 May 20 10:40 filec
- シンボリックリンク
fileb: リンクが「切れた(壊れた)」状態になります。依然としてfileaという「名前」を指していますが、その名前を持つファイルが存在しなくなったためです。多くのターミナルでは、この切れた状態を示すためにfilebのファイル名が赤色で表示されます。cat filebを実行しようとするとエラーになります。 - ハードリンク
filec: ファイルfilecは全く影響を受けません。リンクカウント(第 2 列)が 2 から 1 に減っただけです。ファイルとそのデータは依然としてそのまま残っています。これは、fileaを削除しても i ノードを指す名前の 1 つが消えただけで、リンクカウントが 0 にならない限りデータは削除されないためです。内容を表示して確認してみましょう。
cat filec
元の内容がそのまま表示されます。
This is filea.
では、今度は filea を別の内容で再作成してみましょう。vi を使って filea という名前の新しいファイルを作成します。
viを起動します:vi fileaiを押して挿入モードに入ります。- 新しい内容を入力します:
This is the new filea. Escを押してコマンドモードに戻り、ZZで保存して終了します。
新しい filea が作成された状態で、再度 3 つのファイルを ls -il で確認します。
ls -il file[a-c]
出力は新しい状況を示しています。
131080 -rw-r--r-- 1 labex labex 20 May 20 11:05 filea
131076 lrwxrwxrwx 1 labex labex 5 May 20 10:41 fileb -> filea
131075 -rw-r--r-- 1 labex labex 14 May 20 10:40 filec
- 新しい
filea: 新しいfileaが存在しますが、その i ノード番号(例:131080)はfilecの i ノード(例:131075)とは異なっていることに注目してください。これは、たまたま古いファイルと同じ名前を持っているだけの、完全に新しいファイルです。 - シンボリックリンク
fileb: リンクが復活しました!自動的にfileaという名前の新しいファイルを指すようになります。 - ハードリンク
filec:filecは変化していません。依然として元の i ノードを指しており、元のデータを保持しています。
最後に、3 つのファイルの内容をすべてチェックして結果を確認しましょう。
cat filea
cat fileb
cat filec
出力は違いを明確に示しています。
This is the new filea.
This is the new filea.
This is filea.
シンボリックリンク fileb は名前を追って新しいファイルに繋がりましたが、ハードリンク filec は元のデータへの接続を維持しました。
cp と mv によるファイルのコピーと移動
最後のステップでは、ファイル管理に不可欠な cp(コピー)と mv(移動)コマンドの使い方を学びます。cp コマンドはファイルやディレクトリの複製を作成し、mv コマンドはファイルやディレクトリの名前を変更するか、別の場所に移動させます。
まず、これまでのステップで作成したファイルを削除して、作業スペースをきれいにしましょう。すべてのコマンドは ~/project ディレクトリから実行します。
rm filea fileb filec
cp によるファイルのコピー
cp コマンドは、ファイルの独立した新しいコピーを作成します。新しいファイルは独自の i ノードを持ちます。
- まず、
touchコマンドを使って作業用のシンプルなファイルを作成します。touchはファイルが存在しない場合に空のファイルを作成します。
touch source_file
- 次に、その属性を表示し、i ノード番号(第 1 列)に注目してください。
ls -i source_file
このファイルに割り当てられた一意の i ノード番号が表示されます。
131081 source_file
- 次に、
source_fileをcopied_fileという名前の新しいファイルにコピーします。
cp source_file copied_file
- 両方のファイルの属性をリスト表示します。
ls -i source_file copied_file
これらが異なる i ノード番号を持つ、2 つの別々のファイルであることがわかります。
131082 copied_file
131081 source_file
mv によるファイルの移動と名前変更
mv コマンドは多機能です。移動先が同じディレクトリ内の新しいファイル名であれば、ファイルの名前を変更します。移動先がディレクトリであれば、その中にファイルを移動します。同じファイルシステム内で名前を変更したり移動したりする場合、i ノード番号は変わりません。コマンドは単にファイルの名前や場所のポインタを更新するだけです。
source_fileの名前をrenamed_fileに変更してみましょう。
mv source_file renamed_file
- 新しく名前が付けられたファイルの i ノードを確認します。
ls -i renamed_file
i ノード番号(例:131081)が元の source_file と同じであることに気づくはずです。ファイル自体は変更されず、名前だけが変わりました。
131081 renamed_file
- 次に、このファイルを移動させます。まず、移動先のディレクトリを作成します。
mkdir move_destination
renamed_fileをmove_destinationディレクトリに移動します。
mv renamed_file move_destination/
- ファイルがディレクトリ内にあることを確認し、再度 i ノードをチェックします。
ls -i move_destination/renamed_file
i ノード番号は変わっていません。これはファイルがコピーされたのではなく、移動されたことを裏付けています。
131081 move_destination/renamed_file
上書きの処理
デフォルトでは、多くのシステムで cp は cp -i のエイリアス(別名)として設定されており、既存のファイルを誤って上書きするのを防ぐようになっています。-i は「interactive(対話的)」を意味します。
copied_fileをmove_destinationディレクトリ内のファイルに上書きコピーしようとしてみましょう。
cp -i copied_file move_destination/renamed_file
-iオプション(またはエイリアス)により、確認のプロンプトが表示されます。
cp: overwrite 'move_destination/renamed_file'?
上書きを確定するには y を入力して Enter を押します。キャンセルしたい場合は n を入力します。
まとめ
この実験では、Linux 環境でファイルとディレクトリを管理するための基本的なコマンドを学びました。mkdir を使ったディレクトリ構造の作成(親ディレクトリを同時に作成する -p オプションを含む)、空のディレクトリを削除する rmdir、そして空でないディレクトリを削除する rm の使い方を練習しました。また、vi エディタを使用してファイルを作成し、ファイルのリンクという概念についても学習しました。
実験の核心部分は、2 種類のリンクの作成と分析でした。ln -s によるシンボリックリンク(ソフトリンク)と、ln によるハードリンクです。i ノードを調査し、元のファイルが変更または削除されたときに各リンクがどのように動作するかを確認することで、それらの重要な違いを観察しました。最後に、cp コマンドでファイルの独立したコピーを作成し、mv コマンドでファイルやディレクトリの移動や名前変更を行う方法を学び、主要なファイル管理操作を一通り習得しました。



