【Linux】find -nameでファイル名で検索する方法

シェル/bash

こんにちは。

普段はIT業界についてのブログを執筆してるエンジニアです。
» 参考:プログラマーの年収は200万円以下です【IT業界の残酷な成功法則】

今回は、linuxについての解説記事です。

linuxのfindコマンドでファイル検索したい人

linuxのfindコマンドでファイル検索したい人
「linuxでfindを使ったファイル検索をしたいです。ファイル名の指定には正規表現も使えますか?どのように書いたら良いかわかりやすく具体的を示してください。」

こんな悩みを解決します。

この記事を書いている私はIT業界歴12年、うちサーバエンジニア歴6年、年収1,000万円ちょっとの金融系エンジニアです。IRIXやSolarisなどのUnixやmac、Linuxなど様々なUNIX系環境を扱ってきました。

これまでの経験を踏まえ、コマンドの解説に留まらず実務視点で利用方法を記事にしました。お役にたちましたら幸いです。

本記事で扱うのはLinux/Macのfindコマンドです

本記事では、LinuxまたはMac環境を前提にしています。MS/DOSのfindコマンドは特定の文字列をファイルから探すもので、Linuxのgrepコマンドに近い振る舞いをします。

本記事の内容

1.【基本的な使い方】find 《DIR》 -name 《FILE》

ファイル名を指定してfindコマンドを実行し、ファイルを検索するには以下の構文を使います。

find 《検索ディレクトリ名》 -name《ファイル名》

このとき、検索ディレクトリの下にサブディレクトリがあれば、サブディレクトリも含めて根こそぎファイル検索をかけます。

2. 【使用例1】ファイル名を指定して検索する

以下の例では、findコマンドを実行し、ファイル検索を行う簡単な例です。

% find . -name "file1.txt"

検索ディレクトリの下のfindtestfindtest2という2つのディレクトリに検索対象のfile1.txtがあるとします。実行結果は以下のようになります。

./findtest/file1.txt
./findtest2/file1.txt

3. 【使用例2】ファイル名の一部だけ指定して検索する【正規表現】

正規表現を使用することで、ファイル名の一部だけ指定して検索することができます。

% find . -name "file*.txt"

検索ディレクトリの下のfindtestとfindtest2という2つのディレクトリに検索対象のfile[1〜3].txtがあるとします。実行結果は以下のようになります。

./findtest/file1.txt
./findtest/file2.txt
./findtest/file3.txt
./findtest2/file1.txt
./findtest2/file2.txt
./findtest2/file3.txt

ファイル名の数字を指定して、以下のように記述しても同じ結果を得られます。

% find . -name "file[1-3].txt"

4. findの結果にタイムスタンプやパーミッション情報も表示する

find 《検索ディレクトリ名》 -name 《ファイル名》 -ls

find -lsオプションの使用例

ls -lを実行した時のように、見つかったファイルの情報を詳細に出すには-lsオプションを使います。

% find . -name "file[1-3].txt" -ls

結果は以下の通りです。

29178829  0 -rw-r--r--    1 root   staff  0  7 25 21:41 ./findtest2/file2.txt
29178831  0 -rw-r--r--    1 root   staff  0  7 25 21:41 ./findtest2/file3.txt
29178827  0 -rw-r--r--    1 root   staff  0  7 25 21:41 ./findtest2/file1.txt
29178727  0 -rw-r--r--    1 root   staff  0  7 25 21:38 ./findtest/file2.txt
29178730  0 -rw-r--r--    1 root   staff  0  7 25 21:38 ./findtest/file3.txt
29178725  0 -rw-r--r--    1 root   staff  0  7 25 21:38 ./findtest/file1.txt

5. find -nameとlsの違い

ファイルを検索する際にlsよりfindを用いるメリットは、サブディレクトリ内の検索もできることです。zshまたはbashの拡張競うでglobstarを用いれば、lsでも前の例と同じ結果を得られます。以下に例を示します。

% ls -l **/file[1-3].txt

findでもlsでも同じ結果が得られますが、うまく機能しないこともあります。

  • 検索するファイルの数が少ない場合、どちらを使ってもいい
  • 検索するファイルの数が多い場合、find -nameを使う

幾つか理由がありますが、lsの*や**を使った場合は、シェルが*や**を実態のファイルパスに変換してからコマンドが実行されるので、実際は次のように処理されます。

% ls -l ./findtest/file1.txt ./findtest/file2.txt ./findtest/file3.txt ./findtest2/file1.txt ./findtest2/file2.txt ./findtest2/file3.txt

そのため、ファイル数が多いと引数が多すぎてエラーとなってしまうのです。

この他、処理するアルゴリズムや処理の多様さの面でfindの方がずっとリッチです。簡単なファイル操作はls、より複雑・より負荷の高い検索はfind -nameを使うと覚えて置くと良いでしょう。

6. 開発・運用業務上の注意点

上述している通り、対象のファイル数が多いとCPU負荷が高くなりますので、環境を共有している場合には他の人のテストや業務に影響を与えないよう気を付ける必要があります。

特にfindした結果をパイプ(|)で渡してxargsで処理を行う場合には要注意です。仮にfindの結果見つかったファイルが1,000あれば、xargsによる後続処理によって1,000プロセスが順に起動してしまいます。

このような問題を回避するには、xargsの代わりにfindの-execオプションを使って一ファイルずつ処理するのが良いでしょう。これならば無駄にプロセスが生成されてリソースを消耗することはありません。

今回は以上です。参考になりましたら幸いです。