Linux におけるファイルとディレクトリの管理

CompTIABeginner
オンラインで実践に進む

はじめに

この実験では、Linux のコマンドライン環境でファイルやディレクトリを管理するための基本的なスキルを習得します。mkdirrm を使用して複雑なディレクトリ構造を作成・削除したり、cpmv を使ってファイルやディレクトリをコピー・移動したりする実戦的な経験を積むことができます。

さらに、この実験ではファイルの「リンク」についても詳しく掘り下げます。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 つのモードがあります。起動時はコマンドモードになっており、キー入力はコマンドとして解釈されます。文字を入力するには、挿入モードに切り替える必要があります。

  1. ターミナル(パスは ~/project であるはずです)で vi を起動し、filea を作成します。
vi filea
  1. ターミナルに vi のエディタ画面が表示されます。入力を開始するには、i キーを 1 回押して挿入モードに切り替えます。画面の下部に -- INSERT -- と表示される場合があります。
  2. 次のテキストを入力します。
This is filea.
  1. ファイルを保存して 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 のパーミッション文字列は - で始まっており、通常のファイルであることを示しています。一方、filebl で始まっており、シンボリックリンクであることを示しています。
  • リンクのポインタ: 出力には fileb -> filea と明確に表示されています。
  • i ノード番号: 最初の列を見てください。fileafileb の i ノード番号は異なります。なぜなら、シンボリックリンクはターゲットファイルへのパスを保存しているだけの「別のファイル」だからです。リンク自体が独立したファイルであるため、独自の i ノードを持ちます。

最後に、リンク経由で内容を読み取れるか確認しましょう。

cat fileb

filea の内容が表示されます。

This is filea.

これは期待通りの動作です。シンボリックリンクに対して cat などの操作を行うと、システムは自動的にリンクを辿って元のファイルにアクセスし、操作を実行します。

ln と i ノードによるハードリンクの作成と分析

このステップでは、ハードリンクを作成し、それが前のステップで作成したシンボリックリンクとどのように違うのかを学びます。ファイル名へのポインタであるシンボリックリンクとは異なり、ハードリンクは「ファイルそのものに対する別の名前」です。どちらの名前も、ディスク上の同じデータ(i ノードという一意の番号で識別される)を直接指し示します。

引き続き ~/project ディレクトリにある fileafileb を使用します。

まず、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 列): fileafilec全く同じ i ノード番号(例:131075)を持っていることに注目してください。これがハードリンクの決定的な特徴です。これらは別々のファイルではなく、ディスク上の同一のファイルデータを指す 2 つの異なる名前に過ぎません。一方、シンボリックリンク fileb は独自の i ノードを持っています。
  • リンクカウント(第 2 列): fileafilec の数字を見てください。2 になっています。この数字はハードリンクカウントと呼ばれ、この 1 つの i ノードを指している名前(ハードリンク)がいくつあるかを追跡しています。filec を作成したことで、この i ノードのリンクカウントが 1 から 2 に増えました。
  • ファイルタイプ(パーミッションの 1 文字目): filecfilea と同様に通常のファイル(- で始まる)としてリストされています。filebl で始まる)のような特殊なリンクタイプではありません。

元ファイルを変更した後のリンクの挙動の観察

このステップでは、元のファイルが削除され、その後に再作成されたときに、シンボリックリンクとハードリンクの挙動にどのような決定的な違いが生じるかを観察します。これにより、各リンクの仕組みについての理解が深まります。引き続き ~/project ディレクトリの fileafilebfilec を使用します。

まず、元のファイル 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 という名前の新しいファイルを作成します。

  1. vi を起動します:vi filea
  2. i を押して挿入モードに入ります。
  3. 新しい内容を入力します:This is the new filea.
  4. 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 ノードを持ちます。

  1. まず、touch コマンドを使って作業用のシンプルなファイルを作成します。touch はファイルが存在しない場合に空のファイルを作成します。
touch source_file
  1. 次に、その属性を表示し、i ノード番号(第 1 列)に注目してください。
ls -i source_file

このファイルに割り当てられた一意の i ノード番号が表示されます。

131081 source_file
  1. 次に、source_filecopied_file という名前の新しいファイルにコピーします。
cp source_file copied_file
  1. 両方のファイルの属性をリスト表示します。
ls -i source_file copied_file

これらが異なる i ノード番号を持つ、2 つの別々のファイルであることがわかります。

131082 copied_file
131081 source_file

mv によるファイルの移動と名前変更

mv コマンドは多機能です。移動先が同じディレクトリ内の新しいファイル名であれば、ファイルの名前を変更します。移動先がディレクトリであれば、その中にファイルを移動します。同じファイルシステム内で名前を変更したり移動したりする場合、i ノード番号は変わりません。コマンドは単にファイルの名前や場所のポインタを更新するだけです。

  1. source_file の名前を renamed_file に変更してみましょう。
mv source_file renamed_file
  1. 新しく名前が付けられたファイルの i ノードを確認します。
ls -i renamed_file

i ノード番号(例:131081)が元の source_file と同じであることに気づくはずです。ファイル自体は変更されず、名前だけが変わりました。

131081 renamed_file
  1. 次に、このファイルを移動させます。まず、移動先のディレクトリを作成します。
mkdir move_destination
  1. renamed_filemove_destination ディレクトリに移動します。
mv renamed_file move_destination/
  1. ファイルがディレクトリ内にあることを確認し、再度 i ノードをチェックします。
ls -i move_destination/renamed_file

i ノード番号は変わっていません。これはファイルがコピーされたのではなく、移動されたことを裏付けています。

131081 move_destination/renamed_file

上書きの処理

デフォルトでは、多くのシステムで cpcp -i のエイリアス(別名)として設定されており、既存のファイルを誤って上書きするのを防ぐようになっています。-i は「interactive(対話的)」を意味します。

  1. copied_filemove_destination ディレクトリ内のファイルに上書きコピーしようとしてみましょう。
cp -i copied_file move_destination/renamed_file
  1. -i オプション(またはエイリアス)により、確認のプロンプトが表示されます。
cp: overwrite 'move_destination/renamed_file'?

上書きを確定するには y を入力して Enter を押します。キャンセルしたい場合は n を入力します。

まとめ

この実験では、Linux 環境でファイルとディレクトリを管理するための基本的なコマンドを学びました。mkdir を使ったディレクトリ構造の作成(親ディレクトリを同時に作成する -p オプションを含む)、空のディレクトリを削除する rmdir、そして空でないディレクトリを削除する rm の使い方を練習しました。また、vi エディタを使用してファイルを作成し、ファイルのリンクという概念についても学習しました。

実験の核心部分は、2 種類のリンクの作成と分析でした。ln -s によるシンボリックリンク(ソフトリンク)と、ln によるハードリンクです。i ノードを調査し、元のファイルが変更または削除されたときに各リンクがどのように動作するかを確認することで、それらの重要な違いを観察しました。最後に、cp コマンドでファイルの独立したコピーを作成し、mv コマンドでファイルやディレクトリの移動や名前変更を行う方法を学び、主要なファイル管理操作を一通り習得しました。