【雑学】MacのUnixコマンドで任意のディレクトリ以下のファイルを検索する方法

どーも!

たかぽんです!

今回はMacのターミナルで使用できるUnixコマンドで任意のディレクトリ以下のファイルを検索する方法を調べてみます...!

というのも、たまにCUIでファイルを検索したいなぁと思うことがあるんですが、結局エディタでやっちゃう...みたいなことが多々あり...

エディタでできている間はいいんですが、いざサーバーにはいってできなくなった時とかに困りそうなので、確認をしておきます!

やりたいこと

例えば...

フォルダ構成が以下のようになっていたとします。

Test
├── Test_1
│   ├── Test_11
│   ├── Test_12
│   └── Test_13
├── Test_2
│   ├── Test_21
│   ├── Test_22
│   └── Test_23
└── Test_3
    ├── README.md
    └── Test_4
        ├── Test_41.txt
        ├── Test_42.php
        ├── Test_43.tsx
        ├── Test_44.php
        ├── Test_45.tsx
        └── Test_46.ts

ここから、任意のファイルをファイル名から検索したかったとします。

ここから任意のファイルを検索していく...というのを想定して色々メモをとっていきます。

今回は"Test"ディレクトリがカレントディレクトリとして話を進めます。

色々試していく...!

では、色々試していきます...!

カレントディレクトリ以下の"Test"から始まるディレクトリ、ファイルを検索

まずはカレントディレクトリ以下に対して、"Test"から始まるディレクトリ、ファイルを検索します。

taka@Taka Test % find . -iname "Test*"
./Test_1
./Test_1/Test_13
./Test_1/Test_12
./Test_1/Test_11
./Test_3
./Test_3/Test_4
./Test_3/Test_4/Test_46.ts
./Test_3/Test_4/Test_42.php
./Test_3/Test_4/Test_45.tsx
./Test_3/Test_4/Test_44.php
./Test_3/Test_4/Test_43.tsx
./Test_3/Test_4/Test_41.txt
./Test_2
./Test_2/Test_22
./Test_2/Test_23
./Test_2/Test_21

findの第一引数に検索対象のディレクトリへのpath, -inameとして、検索語を入れてあげればOKです。

ワイルドカードが使用できるので、"Test*"としておけば、Testから始まって、後ろはなにがきてもOKな指定が可能です。

逆に拡張子で絞りたい場合は以下のような形です。

taka@Taka Test % find . -iname "*.tsx"
./Test_3/Test_4/Test_45.tsx
./Test_3/Test_4/Test_43.tsx
taka@Taka Test % find . -iname "*.php"
./Test_3/Test_4/Test_42.php
./Test_3/Test_4/Test_44.php
taka@Taka Test % find . -iname "*.md"
./Test_3/README.md

もちろん、特定のファイル名でも可能です。

taka@Taka Test % find . -iname "Test_42.php"
./Test_3/Test_4/Test_42.php

また、今回は-inameを利用していますが、実は-nameでも検索は可能です。

ただ、nameだと大文字と小文字を区別するため、"test*"で検索をかけると今回の例ではなにもヒットしません。

筆者の個人的な感覚だと、こういった雑なファイル検索時は大文字小文字区別せずとりあえずそれっぽいの全部出した方が嬉しい気がする...ので、-iname前提で進めていきますので、状況に応じて使い分けてください!

カレントディレクトリ以下の"Test"から始まるディレクトリorファイルを検索

さて、先ほどの出力はディレクトリとファイルどちらも入っていましたが、大抵はどちらかだけ欲しいですよね...!

ので、それも試します!

taka@Taka Test % find . -iname "Test*" -type d
./Test_1
./Test_3
./Test_3/Test_4
./Test_2
taka@Taka Test % find . -iname "Test*" -type f
./Test_1/Test_13
./Test_1/Test_12
./Test_1/Test_11
./Test_3/Test_4/Test_46.ts
./Test_3/Test_4/Test_42.php
./Test_3/Test_4/Test_45.tsx
./Test_3/Test_4/Test_44.php
./Test_3/Test_4/Test_43.tsx
./Test_3/Test_4/Test_41.txt
./Test_2/Test_22
./Test_2/Test_23
./Test_2/Test_21

-typeオプションを利用すればディレクトリのみ、あるいはファイルのみを指定することができます。

楽ちんですね...!

ディレクトリ名や親ディレクトリ等がわかっていて、そのディレクトリに関連するものを出したい場合

例えば"Test_2"というディレクトリがパスに含まれているものや、"/Test_3/Test_4/"というパスが含まれているものを検索できます。

taka@Taka Test % find . -ipath "*/Test_2/*"
./Test_2/Test_22
./Test_2/Test_23
./Test_2/Test_21
taka@Taka Test % find . -ipath "*/Test_3/Test_4/*"
./Test_3/Test_4/Test_46.ts
./Test_3/Test_4/Test_42.php
./Test_3/Test_4/Test_45.tsx
./Test_3/Test_4/Test_44.php
./Test_3/Test_4/Test_43.tsx
./Test_3/Test_4/Test_41.txt

-inameだと、"/"を含めた検索はできませんでした。(ファイル, ディレクトリ名での検索のみ)

pathコマンドを使えば、そういったディレクトリ同士の関係性をを用いての検索が可能です。

ただ、上記だけだと全てがヒットするので、さらにファイル名にあたりが付いている場合などはgrepで絞ります。

a@Taka Test % find . -ipath "*/Test_3/Test_4/*" | grep txt
./Test_3/Test_4/Test_41.txt
taka@Taka Test % find . -ipath "*/Test_3/Test_4/*" | grep tsx
./Test_3/Test_4/Test_45.tsx
./Test_3/Test_4/Test_43.tsx
taka@Taka Test % find . -ipath "*/Test_3/Test_4/*" | grep Test_41
./Test_3/Test_4/Test_41.txt

パスで絞って、さらにファイル名等で絞る...みたいなことが可能ですね。

検索したファイルの末尾3行ずつ表示する

少しトリッキーなところまでみておきます。

検索したファイルの末尾3行づつ出力させてみます...!

taka@Taka Test % find . -ipath "*/Test_3/Test_4/*"
./Test_3/Test_4/Test_46.ts
./Test_3/Test_4/Test_42.php
./Test_3/Test_4/Test_45.tsx
./Test_3/Test_4/Test_44.php
./Test_3/Test_4/Test_43.tsx
./Test_3/Test_4/Test_41.txt
taka@Taka Test % find . -ipath "*/Test_3/Test_4/*" -exec basename {} \; -exec tail -n 3 {} \;
Test_46.ts
third line
fourth line
fifth line
Test_42.php
third line
fourth line
fifth line
Test_45.tsx
third line
fourth line
fifth line
Test_44.php
third line
fourth line
fifth line
Test_43.tsx
third line
fourth line
fifth line
Test_41.txt
third line
fourth line
fifth line

少しわかりづらいかもしれませんが、findコマンドでは、"-exec {任意のコマンド} {}\"というふうにオプションを指定してあげればfindの出力結果に対してlinuxコマンドを適応することができます。

さらに、execは複数いけたので、前述の例では最初にファイル名を表示し、その後そのファイルの末尾から3行を表示しています。

なんとなくのファイル名だけ覚えているけど、中身もみてガッと確認したい場合とかは使えるかも?

また、ここまでに使ってきたfindの結果全てに対して同じようにexecコマンドが利用できるので、使い方を工夫すればいろんなことができそうですね。

まとめ

今回はfindの使い方を確認しました...!

エディターで全検索とかサクッとできるので、普段使うことはあまりないですが、エディタが使えない状況や、使えたとしても柔軟な条件指定やexecみたいな機構はなかなかできないので、ぜひ慣れていきたいところです...!

筆者もこんなに便利なのを初めて知ったので、これからはファイル検索等、できるだけCUI上で書くように意識し用と思います...!

それでわ!

おすすめの記事