マッスル・メモリー

筋肉エンジニアのブログ

【Shell, Linux】特定のディレクトリ内のファイル名でgrepしたい

開発中不要なファイルを削除したいことがよくありますが、そのファイルが他の場所で使用されているかどうかを確認する必要があります。 特に特定のディレクトリ内で一括して調べるには手動で1ファイルずつ調査するのは非効率的です。

そこで、以下のコマンドが役立ちます。

$ ls -F dirname | grep -v / | xargs -I {} grep -rl {} | sort | uniq

コマンドの詳細

このコマンドの各部分を順に見ていきましょう。

ls -F dirname | grep -v /: 指定されたディレクトリ(dir1)内のファイルの一覧を表示します。-Fディレクトリに/が付与されるようになるのでそれをgrepで除外します。

xargs -I {}: xargsは、前のコマンドの出力を引数として次のコマンドに渡すために使用されます。-I {}プレースホルダとして{}を指定し、後続のコマンドで使用できるようにします。

grep -rl {}: grepはテキスト検索ツールで、-rオプションは再帰的に検索、-lオプションは実際の行の内容は表示せずファイルのパスを表示する役割を果たします。ここで、{}は前のコマンドから取得したファイル名と置き換えられます。

sort: sortは行をソートするためのコマンドです。これにより、grepの出力がソートされます。

uniq: uniqは連続する重複した行を1つにまとめるコマンドです。これにより、同じファイルが複数回表示されることを防ぎます。

結果として、このコマンドは指定されたディレクトリ内のファイルに対して、それぞれで検索されたテキストが存在するかを再帰的に検索し、結果をソートして一意のファイルパスのリストを表示します。

使用例

まずはテストする環境を用意

$ ls -R
dir1 dir2 dir3

./dir1:
bar.txt fuga.txt hoge.txt

./dir2:
piyo.txt

./dir3:
dir4

./dir3/dir4:
foo.txt

$ cat dir2/piyo.txt
hoge.txt
aaaaaa

$ cat dir3/dir4/foo.txt
bar.txt
bbbbb

今回dir1ディレクトリ内のbar.txt, fuga.txt, hoge.txtの3ファイルの名前が他のファイル(dir2/piyo.txt, dir3/dir4/foo.txt)で使用されているのかを調べます。

この場合2つのファイルで使用されていると確認できます。

$ ls -F dir1 | grep -v / | xargs -I {} grep -rl {} | sort | uniq
./dir2/piyo.txt
./dir3/dir4/foo.txt

念の為片方のファイルを空にすると、

$ cp /dev/null dir2/piyo.txt
$ cat dir2/piyo.txt

$ ls -F dir1 | grep -v / | xargs -I {} grep -rl {} | sort | uniq
./dir3/dir4/foo.txt

となり./dir3/dir4/foo.txtでしか使用されていないことが分かります。

注意事項

ディレクトリの階層構造を下って再帰的に調べたい場合はls -Rを使って再帰的に調査できます。

$ touch dir1/dir5/maccho.txt
$ ls dir1/dir5/
maccho.txt

$ vim dir2/piyo.txt
$ cat dir2/piyo.txt
maccho.txt

# これだとmaccho.txtを調べられない
$ ls -F dir1 | grep -v / | xargs -I {} grep -rl {} | sort | uniq
./dir3/dir4/foo.txt

# -Rをつけることで再起的に表示される
$ ls -FR dir1 | grep -v / | xargs -I {} grep -rl {} | sort | uniq
./dir2/piyo.txt
./dir3/dir4/foo.txt