自動化を続けていると、ファイルはどんどん増えていきます。毎日の CSV、ログ、バックアップ……。気づいたら1つのディレクトリに何百個もファイルがあって、「先月の CSV だけ見たい」「あのログ、どこに置いたっけ?」と困ることがあります。
私も、毎朝 CSV を書き出す自動化を作ったあと、ファイルが増えすぎて ls の画面が流れていってしまい、目的のファイルを目で探すのをあきらめたことがあります。
そんなときに役立つのが、名前の一部だけで指定できるワイルドカードと、ディレクトリの奥まで探してくれる find です。この記事では、練習用のファイルをたくさん作って、目的の1つを探し出す練習をしてみましょう。
- ワイルドカード(
*・?・[ ])で、まとめてファイルを指定する方法 -
findで、名前・種類・更新日時からファイルを探す方法 - 「Permission denied」がたくさん出るときの見やすくする方法
- 見つけたファイルをまとめて消す前に、確かめておくこと
-
ls・cd・mkdir・touchが使える - 相対パスと絶対パス(=いちばん上の
/から書いた場所)がわかる
まだの方は、前の記事「Linuxのaptでソフトを入れる・更新する・消す|Debian・Ubuntuの基本【初心者向け】」や、Lv1 の記事から読むのがおすすめです。
- ログ:プログラムが残す「いつ、何が起きたか」の記録
- ディレクトリ:フォルダのこと
- パス:ファイルやディレクトリの場所を表す「住所」の書き方(/home/kaito など)
- ディスク:データをしまっておく部品(SSD など)。電源を切っても消えません
用語で迷ったら、連載のまとめ記事の「よく出てくる用語ミニ辞典」でも確かめられます。
結論:今いる場所なら「ワイルドカード」、奥まで探すなら「find」
| やりたいこと | 書き方の例 | 意味 |
|---|---|---|
| .csv で終わるファイルを全部 | ls *.csv | * は「何文字でも」 |
| 1文字だけちがうファイル | ls app.log.? | ? は「ちょうど1文字」 |
| 7月か8月のファイル | ls sales-2026-0[78]-* | [ ] は「この中のどれか1文字」 |
| 奥のディレクトリまで名前で探す | find . -name "*.csv" | 今いる場所から下を全部探す |
| ディレクトリだけ探す | find . -type d | d はディレクトリ、f はファイル |
| 最近変わったファイルを探す | find . -mmin -60 | 60分以内に変わったもの |
準備:練習用のファイルをたくさん作る
練習は ~/linux-practice/find-test の中で行います。次のコマンドを、上から順番に打ってください(中身は空のファイルです)。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
mkdir -p ~/linux-practice/find-test
cd ~/linux-practice/find-test
mkdir -p data logs old
touch data/sales-2026-07-01.csv data/sales-2026-07-02.csv data/sales-2026-08-01.csv data/memo.txt
touch logs/app.log logs/app.log.1 logs/app.log.2 logs/error.log
touch old/sales-2025-12-31.csv
ls -Rここから先の出力例は、Debian 13での実行例です(ユーザー名 kaito・パソコン名 demo のダミー環境)。UbuntuやWSL(=Windows の中で Linux を動かせる、Microsoft のしくみ)では、表示が少し違うことがあります。
(例)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
kaito@demo:~/linux-practice/chmod-test$ mkdir -p ~/linux-practice/find-test
kaito@demo:~/linux-practice/chmod-test$ cd ~/linux-practice/find-test
kaito@demo:~/linux-practice/find-test$ mkdir -p data logs old
kaito@demo:~/linux-practice/find-test$ touch data/sales-2026-07-01.csv data/sales-2026-07-02.csv data/sales-2026-08-01.csv data/memo.txt
kaito@demo:~/linux-practice/find-test$ touch logs/app.log logs/app.log.1 logs/app.log.2 logs/error.log
kaito@demo:~/linux-practice/find-test$ touch old/sales-2025-12-31.csv
kaito@demo:~/linux-practice/find-test$ ls -R
.:
data logs old
./data:
memo.txt sales-2026-07-01.csv sales-2026-07-02.csv sales-2026-08-01.csv
./logs:
app.log app.log.1 app.log.2 error.log
./old:
sales-2025-12-31.csv.: は「今いる場所」、./data: は「その下の data の中」という意味の見出しです。
ls -R の -R は、「下のディレクトリの中身も全部表示する」という意味です。
ワイルドカード:名前の一部で、まとめて指定する
*(アスタリスク):何文字でも
* は「どんな文字が何文字あってもいい」という意味です。
- 1
- 2
- 3
cd ~/linux-practice/find-test/data
ls *.csv
ls sales-2026-07-*(例)
- 1
- 2
- 3
- 4
- 5
kaito@demo:~/linux-practice/find-test$ cd ~/linux-practice/find-test/data
kaito@demo:~/linux-practice/find-test/data$ ls *.csv
sales-2026-07-01.csv sales-2026-07-02.csv sales-2026-08-01.csv
kaito@demo:~/linux-practice/find-test/data$ ls sales-2026-07-*
sales-2026-07-01.csv sales-2026-07-02.csv?(はてな):ちょうど1文字
? は「ちょうど1文字」という意味です。
- 1
- 2
- 3
cd ~/linux-practice/find-test/logs
ls app.log.?
ls app.log*(例)
- 1
- 2
- 3
- 4
- 5
kaito@demo:~/linux-practice/find-test/data$ cd ~/linux-practice/find-test/logs
kaito@demo:~/linux-practice/find-test/logs$ ls app.log.?
app.log.1 app.log.2
kaito@demo:~/linux-practice/find-test/logs$ ls app.log*
app.log app.log.1 app.log.2app.log.? は「app.log. のあとに1文字ある」ものだけなので、app.log そのものは入りません。* は「0文字」でもいいので、app.log も入ります。
[ ](角かっこ):この中のどれか1文字
- 1
- 2
- 3
cd ~/linux-practice/find-test/data
ls sales-2026-0[78]-*
ls sales-2026-0[8]-*(例)
- 1
- 2
- 3
- 4
- 5
kaito@demo:~/linux-practice/find-test/logs$ cd ~/linux-practice/find-test/data
kaito@demo:~/linux-practice/find-test/data$ ls sales-2026-0[78]-*
sales-2026-07-01.csv sales-2026-07-02.csv sales-2026-08-01.csv
kaito@demo:~/linux-practice/find-test/data$ ls sales-2026-0[8]-*
sales-2026-08-01.csv[78] は「7 か 8 のどちらか1文字」という意味です。[0-9] のように書くと、「0〜9 のどれか1文字」になります。
ワイルドカードの正体を見てみる
実は、ワイルドカードを広げているのは、コマンドではなくシェルです。echo を使うと、シェル(=打ったコマンドを読み取って、プログラムを動かし、結果を返してくれるプログラム)が * を何に置きかえたのかが見えます。
- 1
- 2
echo *.csv
echo "*.csv"(例)
- 1
- 2
- 3
- 4
kaito@demo:~/linux-practice/find-test/data$ echo *.csv
sales-2026-07-01.csv sales-2026-07-02.csv sales-2026-08-01.csv
kaito@demo:~/linux-practice/find-test/data$ echo "*.csv"
*.csv"(ダブルクォート)で囲むと、ワイルドカードは広がらず、そのままの文字として扱われます。このあと find で "*.csv" と囲んで書くのは、シェルではなく find 自身に * を渡すためです。
ワイルドカードは、cp・mv・rm などのコマンドでも使えます。特に rm と組み合わせるときは、同じ指定で先に ls を打って、何が対象になるのかを確かめてからにしましょう。rm の記事で紹介した「消す前に ls」の習慣です。
find:下のディレクトリまで探す
ワイルドカードは「今いるディレクトリ」が基本です。下のディレクトリまでまとめて探したいときは、find を使います。
- 1
find 探し始める場所 条件名前で探す:-name
- 1
- 2
cd ~/linux-practice/find-test
find . -name "*.csv"(例)
- 1
- 2
- 3
- 4
- 5
- 6
kaito@demo:~/linux-practice/find-test/data$ cd ~/linux-practice/find-test
kaito@demo:~/linux-practice/find-test$ find . -name "*.csv"
./data/sales-2026-07-02.csv
./data/sales-2026-07-01.csv
./data/sales-2026-08-01.csv
./old/sales-2025-12-31.csvfind は、名前の順ではなく、ディスクに記録されている順番で表示します。今回も 07-02 が 07-01 より先に出ました。順番は環境によって変わることがあります。
. は「今いる場所から」という意味です。data だけでなく、old の中の CSV まで見つかりましたね。大文字と小文字を区別したくないときは、-name のかわりに -iname を使います。
" で囲み忘れると 今いる find-test には、CSV が直接は置かれていません。そのため、囲み忘れて find . -name *.csv と打っても、シェルが広げるものがなく、たまたま同じ結果になります。ところが、CSV がいくつもある data の中で同じように打つと、シェルが先に *.csv をファイル名の並びに広げてしまい、find は「-name のあとに名前が2つ以上ある」と受け取って、find: paths must precede expression のようなエラーで止まります。「場所によって動いたり動かなかったりする」のを防ぐために、find の名前はいつも " で囲むと覚えておきましょう。
種類で探す:-type
- 1
- 2
find . -type d
find . -type f -name "app*"(例)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
kaito@demo:~/linux-practice/find-test$ find . -type d
.
./data
./logs
./old
kaito@demo:~/linux-practice/find-test$ find . -type f -name "app*"
./logs/app.log.1
./logs/app.log
./logs/app.log.2-type d はディレクトリだけ、-type f はファイルだけです。条件は、このようにいくつも並べて絞り込めます。
更新日時で探す:-mmin・-mtime
- 1
- 2
touch logs/error.log
find . -mmin -5(例)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
kaito@demo:~/linux-practice/find-test$ touch logs/error.log
kaito@demo:~/linux-practice/find-test$ find . -mmin -5
.
./data
./data/memo.txt
./data/sales-2026-07-02.csv
./data/sales-2026-07-01.csv
./data/sales-2026-08-01.csv
./logs
./logs/app.log.1
./logs/app.log
./logs/error.log
./logs/app.log.2
./old
./old/sales-2025-12-31.csv記事のとおりに続けて打つと、このように全部の13行が出ます。練習用のファイルを作ってから30秒もたたないうちに実行したので、直前に作ったファイルとディレクトリは、全部 -mmin -5(5分以内に変わったもの)に入るからです(. は今いる find-test そのものです)。
そこで、5分以上時間をおいてから、もう一度 touch logs/error.log と find . -mmin -5 を打ち直してみました。
(例:5分以上たってから打ち直したとき)
- 1
- 2
- 3
- 4
kaito@demo:~$ cd ~/linux-practice/find-test
kaito@demo:~/linux-practice/find-test$ touch logs/error.log
kaito@demo:~/linux-practice/find-test$ find . -mmin -5
./logs/error.log今度は ./logs/error.log の1行だけになりました。時間をおいてから touch したファイルだけが出るわけです。touch が変えるのは error.log 自身の日時で、入れ物の logs の日時は変わらないからです(入れ物の日時が変わるのは、中にファイルを作ったり消したりしたときです)。
| 書き方 | 意味 |
|---|---|
-mmin -5 | 5分以内に変わったもの |
-mtime -1 | 1日(24時間)以内に変わったもの |
-mtime +30 | 30日より前に変わったもの |
「昨日の自動化で、どのファイルが書き換わった?」を調べるときに便利です。
空のファイルを探す:-empty
- 1
find . -type f -empty(例)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
./data/memo.txt
./data/sales-2026-07-02.csv
./data/sales-2026-07-01.csv
./data/sales-2026-08-01.csv
./logs/app.log.1
./logs/app.log
./logs/error.log
./logs/app.log.2
./old/sales-2025-12-31.csv自動化がうまく動かず「中身が空のまま」になったファイルを探すときに使えます。
システムの中を探すと「Permission denied」が並ぶ
/etc のようなシステムのディレクトリを探すと、読む権限のない場所で「Permission denied」がたくさん出ることがあります。
- 1
find /etc -name "*.conf"(例:先頭の部分)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
/etc/dhcpcd.conf
/etc/ld.so.conf
/etc/e2scrub.conf
find: ‘/etc/credstore.encrypted’: Permission denied
/etc/nsswitch.conf
find: ‘/etc/ssl/private’: Permission denied
/etc/lighttpd/conf-available/90-javascript-alias.conf途中にも、もう1行あります。
(例:途中の部分)
- 1
- 2
- 3
/etc/xattr.conf
find: ‘/etc/credstore’: Permission denied
/etc/mke2fs.conf今回の環境では、Permission denied(許可がありません)の行が3行まざりました。/etc/ssl/private などは、root(=Linux の管理者ユーザー)しか中を見られないディレクトリです。エラーの行では、場所の名前が ‘ ’ という向きのある引用符で囲まれます。なお、lighttpd・apache2・exim4 などの設定が見つかっているのは、検証に使った環境に入っていたソフトのものです。見つかるファイルは、環境によって変わります。
見つかったファイルの行と、エラーの行がまざって見にくいですね。そんなときは、最後に 2>/dev/null をつけると、エラーの行だけを捨てて見やすくできます。
- 1
find /etc -name "*.conf" 2>/dev/null(例:先頭の部分)
- 1
- 2
- 3
- 4
- 5
- 6
/etc/dhcpcd.conf
/etc/ld.so.conf
/etc/e2scrub.conf
/etc/nsswitch.conf
/etc/lighttpd/conf-available/90-javascript-alias.conf
/etc/lighttpd/conf-enabled/90-javascript-alias.confPermission denied の行がなくなり、見つかったファイルだけが並びました(今回は全部で52行)。
メッセージが日本語で出る環境では
日本語の設定(ロケール)になっている環境では、エラーの行が日本語で表示されます。今回の Debian 13 で日本語の設定にして、見つかったファイルの行は捨てて(> /dev/null)エラーの行だけを表示すると、次のようになりました。
(例)
- 1
- 2
- 3
find: ‘/etc/credstore.encrypted’: 許可がありません
find: ‘/etc/ssl/private’: 許可がありません
find: ‘/etc/credstore’: 許可がありません2> や /dev/null のしくみは、この Lv2 の「リダイレクト(=コマンドの結果の行き先を、画面からファイルなどに切りかえること)とパイプ」の記事でくわしく説明します。今は「エラーを見えなくするおまじない」くらいで大丈夫です。
find / のように、いちばん上から全部を探すこともできますが、とても時間がかかり、エラーも大量に出ます。「設定なら /etc」「自分のファイルなら ~」のように、探す場所を先に絞るのがコツです。フォルダ構成の記事が、ここで役に立ちます。
見つけたファイルをまとめて消す前に
find には、見つけたファイルをそのまま消す -delete や、見つけたファイルにコマンドを実行する -exec という書き方もあります。とても便利ですが、条件を1つ間違えると、思っていないファイルまでまとめて消えてしまいます。
- 条件を確かめずに「-delete」をつける:
-nameの書き間違いや、探し始める場所の間違いがあっても、見つかったものは確認なしで全部消えます。 - 「-delete」を条件より前に書く:
findは左から順に読むので、-deleteを-nameより前に書くと、探し始めた場所の下が全部消えることがあります。 - ホームやシステムのディレクトリを場所に指定する:
find ~ …やfind / …に-deleteや-exec rmをつけるのは、絶対にやめてください。
どうしてもまとめて消したいときは、まず -delete なしで find を実行して、表示された一覧を目で確かめるのが鉄則です。この連載では、find でまとめて消す練習はしません。
🤖 詰まったらAIに聞こう:find の条件の書き方がわからない
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
Linuxの初心者です。find で、次の条件に合うファイルを探したいです。
まずは「探して一覧を表示するだけ」のコマンドを、条件ごとの意味つきで教えてください。
消したり書き換えたりするオプション(-delete や -exec rm など)は使わないでください。
【使っている環境】WSLのUbuntu など
【探し始める場所】例:~/linux-practice/find-test
【探したいもの】例:7月の csv で、中身が空のもの
【試したコマンド】ここに貼る
【表示されたメッセージ】ここに貼るfind の結果には、ファイル名やディレクトリ名がそのまま並びます。取引先の名前、お客さまの名前、メールアドレスなどがファイル名に入っていることもあるので、AI に貼る前に見直して、必要なら「***」に置き換えてください。パスワードやAPIキー(=API を使うときに必要な、合言葉のような文字列)は、もちろん貼らないでくださいね。
よくある質問
Q. ls *.txt と打ったら「No such file or directory」と出ました。
今いる場所に、.txt で終わるファイルが1つもないときに出ます。当てはまるものがないと、シェルは *.txt を広げずに、そのままの文字で ls に渡します。ls は「*.txt という名前のファイル」を探して、見つからないと答えているわけです。pwd で今いる場所を確かめて、ls で中身を見直してみてください。
Q. -mtime +30 は「ちょうど30日前」も入りますか?
入りません。find は日数を「24時間を1日として、端数を切り捨てた数」で比べるため、+30 は「31日以上前」のものになります。「30日くらいより前」と考えておけば、ふだんの使い方では困りません。
Q. 見つけたファイルを、消すのではなく1か所に集めたいです。
まずは find で一覧を出して、何が見つかるかを確かめるところまでにしましょう。まとめて動かす方法(-exec など)はいくつかありますが、消すときと同じく、条件を間違えると大事なファイルまで動いてしまいます。慣れるまでは、一覧を見ながら mv で1つずつ動かすのが安全です。
まとめ
- ワイルドカード:
*は何文字でも、?はちょうど1文字、[ ]はこの中のどれか1文字 - ワイルドカードを広げているのはシェル。
"で囲むとそのままの文字になる - 下のディレクトリまで探すなら
find 場所 条件 - よく使う条件は
-name・-type・-mmin・-mtime・-empty - エラーの行が多いときは
2>/dev/null - まとめて消す前に、必ず一覧を目で確かめる
次の記事では、ファイルを探すのではなく、ファイルの中から目的の1行を探す grep を見ていきます。
次に読む記事
関連する記事
- Pythonで毎日の作業を自動化する入門|ダウンロードフォルダを自動で整理しよう:増えていくファイルを、Python で自動で整理したい方に
- プロが使う.gitignoreパターン集|現場で効くテンプレ:
*.logのようなワイルドカードの書き方を、Git でも活用したい方に - Excel・CSVを毎回手で結合していませんか?Pythonで1分にする方法(重複削除・列名ゆれ対応):find で見つけた CSV を、まとめて1つにしたい方に