はじめに
この実験では、Linux のコマンドライン環境でファイルやコマンドを特定するための不可欠なテクニックを習得します。まずは強力な find コマンドから始め、名前による基本的な検索方法や、より柔軟なパターンマッチングを可能にするワイルドカードの活用方法を学びます。この実践的なアプローチでは、検索スキルを安全に練習するために、サンプル用のディレクトリ構造を作成しながら進めていきます。
基礎を固めた後は、-exec や xargs を使用して、検索結果に対して直接コマンドを実行する方法を探ります。また、データベースを利用した高速な locate コマンド、コマンドのバイナリやマニュアルを探すための whereis、そしてコマンドの実行パスを解析するための alias、which、type といった代替ツールや専門的な検索ツールについても学習します。最終的には、Linux におけるあらゆるファイルやコマンドの検索タスクに対して、最適なツールを選択できるようになります。
find とワイルドカードを使用した基本的なファイル検索
このステップでは、Linux コマンドラインでファイルやディレクトリを検索するための最も強力なツールの 1 つである find コマンドの使い方を学びます。まずは名前ベースの基本的な検索から始め、ファイルパターンを見つけるためのワイルドカードを導入します。
まず、練習用の専用ディレクトリとサンプルファイルを作成しましょう。これにより、ファイルシステムの他の部分に影響を与えることなく、find の動作を確認できる制御された環境を確保できます。
- 正しい開始ディレクトリにいることを確認します。この実験のすべての作業は
~/project内で行います。
cd ~/project
find_labという名前の新しいディレクトリを作成し、その中に移動します。
mkdir find_lab
cd find_lab
- 次に、検索対象となる一連のファイルとサブディレクトリを作成します。空のファイルを作成するには
touchコマンドを、ディレクトリを作成するにはmkdirを使用します。
touch file1.txt file2.log report.txt File1.TXT
mkdir subdir
touch subdir/file3.txt subdir/another.log
現在のディレクトリとそのサブディレクトリ内のファイルを再帰的にリスト表示する ls -R コマンドで、構造を確認できます。
ls -R
次のような出力が表示されるはずです。
.:
File1.TXT file1.txt file2.log report.txt subdir
./subdir:
another.log file3.txt
テスト環境が整ったので、検索を開始しましょう。
find コマンドの基本構文は find [path] [expression] です。[path] は find に検索を開始する場所を指示し、[expression] は何を探すかを定義します。
正確なファイル名による検索
正確な名前でファイルを検索するには、-name 式を使用します。report.txt というファイルを探してみましょう。パスには . を使用します。これは find に現在のディレクトリから検索を開始するように指示するものです。
find . -name "report.txt"
出力には、見つかったファイルへのパスが表示されます。
./report.txt
ワイルドカードを使用した検索
ワイルドカードを使用すると、パターンに基づいてファイルを検索できます。最も一般的なワイルドカードはアスタリスク(*)で、任意の文字列に一致します。
find コマンドが実行される前にシェルがワイルドカードを解釈してしまわないよう、パターンをダブルクォーテーション(")で囲むのがベストプラクティスです。
拡張子が .txt で終わるすべてのファイルを探してみましょう。
find . -name "*.txt"
find は現在のディレクトリ(.)とそのすべてのサブディレクトリを再帰的に検索します。
./file1.txt
./report.txt
./subdir/file3.txt
-name は大文字と小文字を区別するため、File1.TXT が見つからなかったことに注意してください。大文字と小文字を区別せずに検索するには、-iname(insensitive name)式を使用します。
find . -iname "*.txt"
これで、大文字小文字に関係なく、.txt で終わるすべてのファイルが出力に含まれます。
./file1.txt
./report.txt
./File1.TXT
./subdir/file3.txt
ファイルタイプによる検索
-type 式を使用して、ファイルやディレクトリなど、特定の種類のファイルシステムオブジェクトのみを探すよう find に指示することもできます。通常のファイルには -type f を、ディレクトリには -type d を使用します。
現在の場所にあるディレクトリのみを探してみましょう。
find . -type d
出力には、現在のディレクトリ(.)と作成した subdir が表示されます。
.
./subdir
式を組み合わせて、より具体的な検索を行うこともできます。例えば、.log で終わるすべてのファイル(ディレクトリではない)を探すには次のようにします。
find . -type f -name "*.log"
このコマンドは、ファイルであり、かつ名前が .log で終わるすべてのアイテムを見つけます。
./file2.log
./subdir/another.log
これで、名前パターンとタイプフィルタを使用した find の基本を学びました。次のステップでは、このコマンドのより高度な機能を探っていきます。
find -exec と xargs を使用した検索結果へのアクション実行
このステップでは、単にファイルをリストアップするだけにとどまりません。find コマンドで見つかったファイルに対して直接コマンドを実行する方法を学びます。これは、権限の変更、ファイルの削除、カスタムスクリプトの実行など、一括操作を行うための強力なテクニックです。主に 2 つの方法、find の -exec オプションと xargs コマンドについて説明します。
前のステップに引き続き、~/project/find_lab ディレクトリで作業を行います。まず、正しいディレクトリにいることを確認してください。
cd ~/project/find_lab
find -exec の使用
-exec オプションを使用すると、find が見つけた各ファイルに対して任意のコマンドを実行できます。構文は最初は少し特殊に見えるかもしれません。
find [path] [expression] -exec [command] {} \;
[command]: 実行したいコマンド(例:ls -l,rm,chmod)。{}: これは特別なプレースホルダーです。findは{}を現在見つかったファイルのフルパスに置き換えます。\;: これは-execコマンドに必要な終端記号です。セミコロンがシェルによって特殊文字として解釈されないように、バックスラッシュ(\)が必要です。
実際に試してみましょう。拡張子が .txt のすべてのファイルを見つけ、それぞれの詳細情報を表示するために ls -l を実行します。
find . -name "*.txt" -exec ls -l {} \;
出力には、見つかった .txt ファイルごとに 1 回ずつ、計 3 回 ls -l が実行された結果が表示されます。
-rw-rw-r-- 1 labex labex 0 Jun 26 09:45 ./file1.txt
-rw-rw-r-- 1 labex labex 0 Jun 26 09:45 ./report.txt
-rw-rw-r-- 1 labex labex 0 Jun 26 09:45 ./subdir/file3.txt
安全のために、find には -ok オプションが用意されています。これは -exec と同様に動作しますが、各ファイルに対してコマンドを実行する前に確認を求めます。ファイルの削除(rm)のような破壊的な操作を行う場合には、このオプションの使用を強くお勧めします。
先ほど作成した .log ファイルを削除してみましょう。今回は安全のために -ok を使用します。
find . -name "*.log" -ok rm {} \;
ファイルが見つかるたびに、find は確認を求めてきます。y を入力して Enter キーを押し、削除を承認してください。
< rm ... ./file2.log > ? y
< rm ... ./subdir/another.log > ? y
確認後、ディレクトリの内容をリスト表示して、ファイルが削除されたことを確認できます。
ls -R
.:
File1.TXT file1.txt report.txt subdir
./subdir:
file3.txt
xargs の使用
-exec の代替案として、find の出力を xargs コマンドにパイプで渡す方法があります。xargs は標準入力(find から提供されるファイルパス)から項目を読み取り、それらの項目を引数として指定されたコマンドを実行します。
xargs の主な利点は効率性です。-exec ... \; はファイルごとに 1 回ずつコマンドを実行しますが、xargs はファイルパスをグループ化し、多くの引数を一度に渡してコマンドの実行回数を減らします。
まず、作業対象を作るために、先ほど削除したログファイルを再作成しましょう。
touch file2.log subdir/another.log
次に、find と xargs を使用して .log ファイルの詳細をリスト表示します。
find . -name "*.log" | xargs ls -l
出力は -exec の例と似ていますが、コマンドの構造が異なります。
-rw-r--r-- 1 labex labex 0 <date> <time> ./file2.log
-rw-r--r-- 1 labex labex 0 <date> <time> ./subdir/another.log
find -ok と同様に、xargs にも -p オプションを使用した「プロンプト」モードがあります。実行しようとしているコマンドを表示し、確認を求めます。
これを使って、もう一度 .log ファイルを削除してみましょう。
find . -name "*.log" | xargs -p rm
xargs はファイルを 1 つの rm コマンドにまとめ、確認を求めます。y を入力して Enter キーを押します。
rm ./file2.log ./subdir/another.log ?...y
これで、検索結果に対してアクションを実行するための -exec と xargs の両方の使い修得しました。これは Linux でタスクを自動化するための基本的なスキルです。
locate と updatedb を使用した高速なデータベース駆動型検索
このステップでは、find の代替ツールである locate について学びます。find がリアルタイムでファイルシステムを検索するのに対し、locate は事前に構築されたファイルパスのデータベースを検索します。これにより locate は大幅に高速になりますが、重要なトレードオフがあります。それは、データベースが最後に更新された時点で存在していたファイルしか見つけられないということです。
引き続き ~/project ディレクトリで作業を進めます。まず、必要なツールがインストールされていることを確認しましょう。
locateコマンドはmlocateパッケージによって提供されますが、デフォルトではインストールされていない場合があります。次のコマンドを実行してパッケージリストを更新し、インストールしてください。システム全体へのインストールとなるため、sudoを使用します。
sudo apt-get update && sudo apt-get install -y mlocate
パッケージのインストールが進行しますが、これは正常な動作です。
- 前のステップで作成したテストディレクトリに移動します。
cd ~/project/find_lab
locateを使用してreport.txtファイルを探してみます。
locate report.txt
多くのシステムでは locate データベースが自動的に更新されるため、すぐにファイルが表示される場合があります。
/home/labex/project/find_lab/report.txt
ファイルパスが表示された場合は、データベースに最近作成したファイルの情報がすでに含まれていることを意味します。これは、システムがバックグラウンドで自動的にデータベース更新を実行したときに起こります。
- ステップ 3 で出力が表示されなかった場合は、データベースを手動で更新する必要があります。
updatedbコマンドを使用してデータベースを再構築します。
sudo updatedb
このコマンドは出力を生成しませんが、バックグラウンドで動作します。完了までに数秒かかる場合があります。
updatedbを実行した後(必要な場合)、再度locateコマンドを試してください。
locate report.txt
今度はファイルへのパスが見つかり、表示されるはずです。
/home/labex/project/find_lab/report.txt
ローカルデータベースの制限事項を理解する
データベースが最後に更新された後に新しいファイルを作成するとどうなるかを確認してみましょう。
- まず、
find_labディレクトリに新しいファイルを作成します。
touch special_report.pdf
- この新しいファイルを
locateで探してみます。
locate special_report.pdf
システムデータベースが直近で更新されていればファイルが表示されるかもしれませんが、そうでなければ、データベースがこの新しく作成されたファイルをまだ認識していないため、何も出力されません。
- システムデータベースの更新を強制的に実行します。
sudo updatedb
- 再度ファイルを検索します。
locate special_report.pdf
今度は次のように表示されるはずです。
/home/labex/project/find_lab/special_report.pdf
データベース更新頻度の理解
重要なポイントは、locate はデータベースの鮮度に依存しているということです。本番システムでは以下のようになります。
- システムは通常、
locateデータベースを自動的に更新します(多くの場合、cron ジョブを介して毎日実行されます)。 - 即座に結果が必要な場合は、
sudo updatedbで手動更新できます。 locateはファイルシステムをスキャンするのではなく、構築済みのインデックスを検索するため、非常に高速です。- 作成されたばかりのファイルを探す場合は、リアルタイムで検索する
findの方が信頼性が高い場合があります。
これで、locate が構築済みデータベースを使用して超高速検索を提供する方法と、updatedb でそのデータベースを最新の状態に保つことの重要性を学びました。
whereis によるコマンドのバイナリとマニュアルの特定
このステップでは、コマンドのバイナリ、ソース、およびマニュアルページファイルを特定するための専門コマンドである whereis の使い方を学びます。汎用的なファイル検索を行う find や locate とは異なり、whereis はシステムコマンドに関連する主要なファイルを素早く見つけるために最適化されています。標準的な Linux ディレクトリの定義済みリストを検索するため、非常に高速に動作します。
まずは whereis コマンドを触ってみましょう。whereis は現在の場所からの相対パスで検索しないため、どのディレクトリにいても構いません。一貫性を保つため、~/project ディレクトリに留まります。
cd ~/project
- ユーザーパスワードを変更するために使用される
passwdコマンドの場所を探してみましょう。
whereis passwd
出力にはコマンド名に続いて、バイナリ実行ファイルと関連するマニュアルページへのパスが表示されます。
passwd: /usr/bin/passwd /etc/passwd /usr/share/man/man1/passwd.1.gz /usr/share/man/man5/passwd.5.gz
/usr/bin/passwd: これは実行プログラムです。/etc/passwd: これはシステムのユーザーデータベースファイルであり、passwdコマンドがやり取りする対象です。whereisは結果に重要な設定ファイルを含めることがよくあります。/usr/share/man/...: これらはコマンドの圧縮されたマニュアルページです。
- 結果をフィルタリングして、特定の種類のファイルのみを表示できます。
passwdに関連するバイナリファイルのみを表示するには、-b(binary)フラグを使用します。
whereis -b passwd
これにより、マニュアルページを除いた、実行ファイルと関連ファイルのみに出力が絞り込まれます。
passwd: /usr/bin/passwd /etc/passwd
- 同様に、マニュアルページのみを探すには
-m(manual)フラグを使用します。これは、コマンドに対してどのようなドキュメントが利用可能かを知りたいときに便利です。
whereis -m passwd
出力にはマニュアルページの場所のみがリストされます。
passwd: /usr/share/man/man1/passwd.1.gz /usr/share/man/man5/passwd.5.gz
whereisの制限を理解しておくことが重要です。これは標準的なシステムディレクトリのみを検索します。find_labディレクトリに作成したreport.txtファイルを探してみましょう。
whereis report.txt
コマンドはファイル名のみを返し、パスは表示されません。
report.txt:
これは、report.txt がホームディレクトリ(~/project/find_lab)にあり、そこがシステムバイナリやマニュアルページの標準的な場所ではないために起こります。これが重要な違いです。個人用ファイルやプロジェクトファイルには find や locate を使い、システムコマンドを調査するには whereis を使用してください。
これで、Linux コマンドを構成するファイルを素早く特定するために whereis を使用する方法を学びました。これはシステム管理やトラブルシューティングに役立つスキルです。
alias、which、type によるコマンドパスの解析
この最後のステップでは、コマンド名を入力したときにシェルがどのコマンドを実行するかをどのように決定するのかを探ります。これは常にディスク上のファイルを見つけるほど単純なわけではありません。シェルには特定の優先順位があります。まず エイリアス(alias) をチェックし、次に シェル組み込みコマンド(shell built-in) を探し、最後にシステムの $PATH 環境変数にリストされているディレクトリから実行ファイルを検索します。ここでは、コマンドのショートカットを作成するための alias と、コマンド名が実際に何を指しているのかを診断するための which および type の使い方を学びます。
まず、一時的なエイリアスを作成して、それがコマンドの実行にどのように影響するかを見てみましょう。~/project ディレクトリに留まります。
- エイリアスは、別のコマンドに対するユーザー定義のショートカットです。
pwdコマンド(現在の作業ディレクトリを表示)を実行すると、代わりにdateコマンドが実行されるようなエイリアスを作成してみましょう。
alias pwd='date'
- ここで
pwdコマンドを実行します。
pwd
エイリアスが優先されるため、現在のディレクトリを表示する代わりに、現在のシステム日時が表示されます。
<現在のシステム日時>
which と type による調査
さて、エイリアスの存在を知らなかったと仮定しましょう。なぜ pwd が期待通りの動作をしないのか、どのようにトラブルシューティングすればよいでしょうか。ここで which と type が役立ちます。
whichコマンドは、$PATH環境変数にリストされているディレクトリから実行ファイルを探します。
which pwd
出力は以下のようになります。
pwd: aliased to date
typeコマンドはより包括的です。これはシェルの組み込みコマンドで、エイリアスや組み込み関数を含め、シェルがコマンド名をどのように解釈するかを説明します。
type pwd
このコマンドは状況を正確に特定します。
pwd is an alias for date
- ある名前に一致するすべての可能性のあるコマンドを表示するには、
-a(all)フラグを使用します。これはtypeと組み合わせると特に強力です。
type -a pwd
これにより、pwd というコマンド名の完全な階層が明らかになります。
pwd is an alias for date
pwd is a shell builtin
pwd is /usr/bin/pwd
pwd is /bin/pwd
この出力は、シェルの優先順位を教えてくれます。まずエイリアスを使用します。エイリアスが存在しない場合は、シェルの組み込みコマンドとしての pwd を使用します。どちらも存在しない場合は、/usr/bin/pwd にあるプログラムを実行します。
エイリアスの削除
最後に、エイリアスを削除して実験の後片付けをしましょう。
unaliasコマンドは、現在のシェルセッションからエイリアスの定義を削除します。
unalias pwd
- 再度
pwdとtype pwdを実行して、すべてが正常に戻ったことを確認します。
pwd
出力:
/home/labex/project
type pwd
出力:
pwd is a shell builtin
これで、エイリアスの作成と削除の方法、そしてさらに重要なこととして、シェルが実際にどのコマンドを実行するのかを正確に理解するために which と type を使用する方法を学びました。
まとめ
この実験では、Linux ファイルシステム全体でファイルやディレクトリを検索する方法を学びました。強力な find コマンドから始め、名前ベースの条件やワイルドカードを使用した基本的な検索を行い、その後 -exec や xargs を使用して検索結果に対してコマンドを実行する高度な手法へと進みました。また、より高速なデータベース駆動型の代替手段として locate コマンドを探索し、updatedb でそのデータベースを維持する方法を学びました。
さらに、この実験ではコマンドを特定し解析するためのテクニックも扱いました。whereis を使用してコマンドのバイナリとマニュアルページの場所を見つけました。コマンドの実行パスを理解するために、呼び出されている特定の実行ファイルを特定する which や、コマンドがエイリアス、組み込み、またはファイルのいずれであるかを判断する type の使い方を学び、エイリアスがコマンドの動作にどのように影響するかを分析しました。



