Linuxでファイルを検索するためのFindおよびLocateの使い方
紹介
Linuxを学び始めたユーザーが直面する問題の一つは、自分が探しているファイルをどのように見つけるかということです。
このガイドでは、適切に名前付けられたfindコマンドの使い方について説明します。これにより、さまざまなフィルターやパラメーターを使用してシステム上のファイルを検索できます。また、異なる方法でファイルを検索するために使用できるlocateコマンドについても簡単に説明します。
前提条件
このガイドに従うには、Linuxベースのオペレーティングシステムを実行しているコンピュータにアクセスする必要があります。これは、SSHで接続した仮想プライベートサーバーまたはローカルマシンのいずれかです。このチュートリアルは、Ubuntu 20.04を実行しているLinuxサーバーを使用して検証されましたが、提供された例は、任意のLinuxディストリビューションの任意のバージョンを実行しているコンピュータでも機能するはずです。
このガイドに従うためにリモートサーバーを使用する予定がある場合は、まず私たちの初期サーバー設定ガイドを完了することをお勧めします。そうすることで、安全なサーバー環境が整備されます — 具体的には、root ユーザーではないユーザーが sudo 権限を持ち、UFW で構成されたファイアウォールが含まれています — これを使用して Linux スキルを構築することができます。
注意: find および locate コマンドの動作を示すために、このガイドの例のコマンドは /、すなわち ルートディレクトリ に保存されているファイルを検索します。そのため、非 ルート ユーザーとしてターミナルにログインしている場合、一部の例のコマンドの出力に Permission denied が含まれることがあります。
これは予想されることであり、通常のユーザーがアクセスできないディレクトリ内でファイルを検索しているためです。しかし、これらの例のコマンドは依然として機能し、これらのプログラムの動作を理解するために役立ちます。
名前で探す
ファイルを検索する最も明白な方法は、その名前によって検索することです。
ファイル名でファイルを見つけるためにfindコマンドを使用する場合、次の構文を使います:
- find -name "query"
これは大文字小文字を区別します。つまり、query の検索は Query の検索とは異なります。
名前でファイルを見つけるが、クエリの大文字小文字を無視するには、-inameオプションを使用します:
- find -iname "query"
特定のパターンに従っていないすべてのファイルを見つけたい場合は、-notを使用して検索を反転させることができます:
- find -not -name "query_to_avoid"
あるいは、感嘆符(!)を使って検索を反転させることもできます。これのように:
- find \! -name "query_to_avoid"
コード「!」を使用する場合は、シェルが「find」の前にそれを解釈しないように、バックスラッシュ(「\」)でその文字をエスケープする必要があります。
タイプで探す
検索したいファイルの種類を -type パラメータで指定できます。動作は次のようになります:
- find -type type_descriptor query
ファイルの種類を指定するために使用できるいくつかの説明子を以下に示します:
f: 通常のファイルd: ディレクトリl: シンボリックリンク- c: キャラクターデバイス
b: ブロックデバイス
例えば、システム上のすべてのキャラクターデバイスを見つけたい場合、このコマンドを入力することができます:
- find /dev -type c
このコマンドは特に、デバイスファイルが通常Linuxシステムでマウントされるディレクトリである/devディレクトリ内のデバイスのみを検索します。
/dev/vcsa5
/dev/vcsu5
/dev/vcs5
/dev/vcsa4
/dev/vcsu4
/dev/vcs4
/dev/vcsa3
/dev/vcsu3
/dev/vcs3
/dev/vcsa2
/dev/vcsu2
/dev/vcs2
. . .
.confで終わるすべてのファイルを、次のようなコマンドで検索できます。この例では、/usrディレクトリ内で一致するファイルを検索します。
- find /usr -type f -name "*.conf"
/usr/src/linux-headers-5.4.0-88-generic/include/config/auto.conf
/usr/src/linux-headers-5.4.0-88-generic/include/config/tristate.conf
/usr/src/linux-headers-5.4.0-90-generic/include/config/auto.conf
/usr/src/linux-headers-5.4.0-90-generic/include/config/tristate.conf
/usr/share/adduser/adduser.conf
/usr/share/ufw/ufw.conf
/usr/share/popularity-contest/default.conf
/usr/share/byobu/keybindings/tmux-screen-keys.conf
/usr/share/libc-bin/nsswitch.conf
/usr/share/rsyslog/50-default.conf
. . .
注意: 前の例では、二つのfindクエリ表現を組み合わせています。すなわち、-type f と -name "*.conf" です。返されるファイルは、これら両方の条件を満たす必要があります。
このように、-andオプションで区切ることで、表現を組み合わせることができますが、この例のように、2つの表現を含む場合は-andが暗黙的に適用されます。また、いずれかの表現を満たす結果を返すためには、-orオプションで区切ります。
- find -name query_1 -or -name query_2
この例では、名前が query_1 または query_2 に一致する任意のファイルを見つけます。
時間とサイズでフィルタリング
findは、サイズや時間で結果をフィルタリングするためのさまざまな方法を提供します。
サイズ
ファイルをサイズでフィルタリングするには、-sizeパラメータを使用します。そのためには、数値サイズの値の末尾に特別なサフィックスを追加して、バイト、メガバイト、ギガバイト、または他のサイズの単位でサイズを測っているかを示す必要があります。ここに一般的に使用されるサイズサフィックスがあります:
c: バイトk: キロバイトM: メガバイト- G: ギガバイト
b: 512バイトのブロック
例として、次のコマンドは、/usr ディレクトリ内のサイズが正確に 50 バイトのすべてのファイルを見つけます:
- find /usr -size 50c
50バイト未満のファイルを見つけるには、代わりにこの構文を使用できます:
- find /usr -size -50c
/usrディレクトリ内で700メガバイト以上のファイルを見つけるには、次のコマンドを使用できます:
- find /usr -size +700M
時間
システム上のすべてのファイルについて、Linuxはアクセス時間、変更時間、および変化時間に関する時間データを保存します。
アクセス時間: ファイルが最後に読み取られたまたは書き込まれた時間。
修正時刻: ファイルの内容が最後に修正された時刻です。
変更時刻: ファイルのinodeメタデータが最後に変更された時刻です。
これらのパラメータに基づいて、find 検索を行うことができます。-atime、-mtime、および -ctime オプションをそれぞれ使用します。これらのオプションのいずれかを使用する場合は、過去何日間を検索したいかを示す値を渡す必要があります。以前に説明したサイズオプションと同様に、これらのオプションにプラスまたはマイナス記号を前置して「より大きい」または「より小さい」を指定できます。
例えば、過去1日以内に変更された/usrディレクトリ内のファイルを見つけるには、次のコマンドを実行します:
- find /usr -mtime 1
もし一日未満にアクセスされたファイルが欲しい場合は、このコマンドを実行できます:
- find /usr -atime -1
メタ情報が最後に変更されたのが3日以上前のファイルを見つけるには、次のコマンドを実行することができます。
- find /usr -ctime +3
これらのオプションには日数の代わりに分を指定するために使える伴随パラメータもあります。
- find /usr -mmin -1
これは、最後の1分間に変更されたファイルを表示します。
find は、参照ファイルと比較を行い、新しいものを返すこともできます。
- find / -newer reference_file
この構文は、リファレンスファイルよりも最近に作成または変更されたシステム上のすべてのファイルを返します。
所有者と権限による検索
ファイルを所有するユーザーまたはグループによってファイルを検索するには、それぞれ -user および -group パラメーターを使用できます。 /var ディレクトリ内の syslog ユーザーが所有するすべてのファイルを見つけるには、このコマンドを実行してください:
- find /var -user syslog
同様に、shadow グループによって所有されている /etc ディレクトリ内のファイルを指定するには、次のように入力してください:
- find /etc -group shadow
特定の権限を持つファイルを検索することもできます。
正確な権限のセットを一致させたい場合は、8進法表記を使用して権限を指定するこの構文を使用できます:
- find / -perm 644
これは、指定された権限と正確に一致するファイルをマッチさせます。
その権限で少なくとも何かを指定したい場合は、権限の表記の前にマイナス符号を付けることができます:
- find / -perm -644
これは追加の権限を持つファイルに一致します。権限が744のファイルは、この場合に一致します。
深さによるフィルタリング
このセクションでは、構造内の深さによってファイルをフィルタリングするために使用する例のディレクトリ構造を作成します。
このチュートリアルの例に従っている場合は、/tmp/ディレクトリ内にこれらのファイルとディレクトリを作成することが賢明です。/tmp/は一時ディレクトリであり、その中のファイルやディレクトリはサーバーが再起動するたびに削除されます。このガイドの目的にとって便利であり、お好きなだけディレクトリ、ファイル、リンクを作成でき、後でシステムが混雑することを心配する必要がありません。
このセクションのコマンドを実行すると、あなたの/tmp/ディレクトリには三層のディレクトリが作成され、最初のレベルには十個のディレクトリがあります。それぞれのディレクトリ(仮ディレクトリを含む)には十個のファイルと十個のサブディレクトリが含まれます。
/tmp/ディレクトリ内に以下のコマンドで例のディレクトリ構造を作成してください:
- mkdir -p /tmp/test/level1dir{1..10}/level2dir{1..10}/level3dir{1..10}
その後、touchコマンドを使用してこれらのディレクトリにいくつかのサンプルファイルを作成します。
- touch /tmp/test/{file{1..10},level1dir{1..10}/{file{1..10},level2dir{1..10}/{file{1..10},level3dir{1..10}/file{1..10}}}}
これらのファイルとディレクトリが配置されたら、今作成したtest/ディレクトリに移動してください:
- cd /tmp/test
findがこの構造からファイルを取得するための基本的な理解を得るには、file1という名前のファイルと一致する通常の名前検索から始める。
- find -name file1
./level1dir7/level2dir8/level3dir9/file1
./level1dir7/level2dir8/level3dir3/file1
./level1dir7/level2dir8/level3dir4/file1
./level1dir7/level2dir8/level3dir1/file1
./level1dir7/level2dir8/level3dir8/file1
./level1dir7/level2dir8/level3dir7/file1
./level1dir7/level2dir8/level3dir2/file1
./level1dir7/level2dir8/level3dir6/file1
./level1dir7/level2dir8/level3dir5/file1
./level1dir7/level2dir8/file1
. . .
これにより多くの結果が返されます。出力をカウンターにパイプすると、合計で1111件の結果があることがわかります:
- find -name file1 | wc -l
1111
これは、おそらくほとんどの状況であなたにとって有用すぎる結果が多すぎます。絞り込むには、最上位の検索ディレクトリの下で検索の最大深度を指定できます。
- find -maxdepth num -name query
level1 ディレクトリとその上位のディレクトリ内でのみ file1 を見つけるには、最大深度を 2 に設定できます (トップレベルのディレクトリ用に 1、level1 ディレクトリ用に 1)
- find -maxdepth 2 -name file1
./level1dir7/file1
./level1dir1/file1
./level1dir3/file1
./level1dir8/file1
./level1dir6/file1
./file1
./level1dir2/file1
./level1dir9/file1
./level1dir4/file1
./level1dir5/file1
./level1dir10/file1
それはずっと管理しやすいリストです。
現在のディレクトリの下で特定のポイントを超えてすべてのファイルが存在することがわかっている場合、最小ディレクトリを指定することもできます。
- find -mindepth num -name query
これを使用して、ディレクトリのブランチの末尾にあるファイルだけを見つけることができます:
- find -mindepth 4 -name file1
./level1dir7/level2dir8/level3dir9/file1
./level1dir7/level2dir8/level3dir3/file1
./level1dir7/level2dir8/level3dir4/file1
./level1dir7/level2dir8/level3dir1/file1
./level1dir7/level2dir8/level3dir8/file1
./level1dir7/level2dir8/level3dir7/file1
./level1dir7/level2dir8/level3dir2/file1
. . .
再度、分岐ディレクトリ構造のため、これは多数の結果(1000)を返します。
最小深度および最大深度のパラメーターを組み合わせて、狭い範囲に焦点を合わせることができます:
- find -mindepth 2 -maxdepth 3 -name file1
./level1dir7/level2dir8/file1
./level1dir7/level2dir5/file1
./level1dir7/level2dir7/file1
./level1dir7/level2dir2/file1
./level1dir7/level2dir10/file1
./level1dir7/level2dir6/file1
./level1dir7/level2dir3/file1
./level1dir7/level2dir4/file1
./level1dir7/file1
. . .
このようにオプションを組み合わせることで、結果が大幅に絞り込まれ、以前の1000行の代わりに110行だけが返されます。
find の結果にコマンドを実行する
find コマンドでマッチするすべてのものに対して、以下の構文を使用して -exec パラメータを使って任意のヘルパーコマンドを実行できます:
- find find_parameters -exec command_and_options {} \;
{}は、findが一致したファイルのプレースホルダーとして使用されます。\;は、findにコマンドの終了位置を知らせます。
たとえば、前のステップで作成した /tmp/ ディレクトリ内の test/ ディレクトリにまだいると仮定すると、前のセクションで 644 権限を持っていたファイルを見つけて、それらの権限を 664 に変更することができます:
- find . -type f -perm 644 -exec chmod 664 {} \;
同様の方法でディレクトリの権限を変更することもできます:
- find . -type d -perm 755 -exec chmod 700 {} \;
この例では、755 に設定された権限を持つすべてのディレクトリを検索し、その後に権限を 700 に変更します。
locateを使用してファイルを見つける
findを使用する代わりに、locateコマンドを使用することができます。このコマンドは、しばしばより速く、ファイルシステム全体を簡単に検索することができます。
DebianまたはUbuntuにおいて、aptを使用してコマンドをインストールするには、パッケージリストを更新し、次にmlocateパッケージをインストールします:
- sudo apt update
- sudo apt install mlocate
Rocky Linux、CentOS、およびその他のRedHat派生ディストリビューションでは、代わりにdnfコマンドを使用してmlocateをインストールできます。
- sudo dnf install mlocate
locateがfindよりも速い理由は、ファイルシステム上のすべてのファイルをリストしたデータベースに依存しているからです。このデータベースは通常、cronスクリプトで1日に1回更新されますが、updatedbコマンドを使って手動で更新することもできます。今すぐsudo権限でこのコマンドを実行してください:
- sudo updatedb
新しいファイルを見つけたい場合は、locate データベースが常に最新である必要があります。cron スクリプトが実行される前や、updatedb コマンドを実行する前に新しいファイルを追加した場合、それらはクエリ結果に表示されません。
locateは、さまざまな方法で結果をフィルタリングできる機能を提供します。ファイルを見つけるための最も基本的な方法は、この構文を使用することです:
- locate query
これは、ファイルパスのどこかに文字列queryを含むすべてのファイルとディレクトリに一致します。ディレクトリ内のクエリが含まれるすべてのファイルの代わりに、名前にクエリ自体を含むファイルのみを返すには、-bフラグを追加して、“ベース名”がクエリに一致するファイルのみを検索できます:
- locate -b query
ファイルシステムにまだ存在する結果のみを返すようにするには(つまり、最後の updatedb 呼び出しと現在の locate 呼び出しの間に削除されなかったファイル)、-e フラグを使用します。
- locate -e query
locateがカタログに登録した情報に関する統計を、-Sオプションを使用して取得できます:
- locate -S
Database /var/lib/mlocate/mlocate.db:
21015 directories
136787 files
7727763 bytes in file names
3264413 bytes used to store database
これは、システム上にどれだけのファイルやディレクトリが存在するかを高レベルで理解するのに役立ちます。
結論
両方のfindおよびlocateコマンドは、あなたのシステム上のファイルを見つけるための有用なツールです。どちらも強力なコマンドであり、他のユーティリティとパイプラインを通じて組み合わせることで更に強化することができますが、どちらのツールがあなたの状況に適しているかを決めるのはあなた次第です。
ここから、findやlocateを使って実験を続けることをお勧めします。それぞれのmanページを読んで、このガイドで取り上げられていない他のオプションについて学ぶことができますし、wc、sort、grepのような別のコマンドにパイプして、検索結果を分析したり操作したりすることができます。
