find | xargs wc -l でディレクトリ配下のファイル数と行数を数える

  • Shell
  • find
  • Linux

この記事は、構成と文章の整理にAIを使っています。
あくまで読みやすくするための補助で、内容そのものをAIにすべて任せて書いているわけではありませんが、ところどころ相談しながら整えています。

ディレクトリ配下のファイル数・行数を数えるワンライナーをいくつか使うので、手元用にまとめておく。

ファイル一覧を出す

$ find app/ -type f

app/ 配下のファイルだけを再帰的に列挙する。-type f を付けないとディレクトリも一緒に出てくる。

1ファイルの行数を数える

$ wc -l filename.txt

これは単純に対象ファイルの行数を返す。

ファイル一覧+行数をまとめて数える

find の結果を xargs 経由で wc -l に渡すと、各ファイルの行数と合計行数が一気に取れる。

$ find app -type f | sort | xargs wc -l
2 app/a.php
1 app/b.txt
1 app/sub/c.php
4 total

sort を挟んでいるのは出力を見やすくするためで、必須ではない。

拡張子を絞りたいときは -name を使う。

$ find app -name '*.php' -type f | sort | xargs wc -l
2 app/a.php
1 app/sub/c.php
3 total

ハマったところ

-type にハイフンを付けると落ちる

-type f と書くべきところを -type -f と書くと、findはこう言って止まる。

$ find app/ -type -f
find: Unknown argument to -type: -

-type の引数は f や d のような1文字で、ハイフンは不要。単純なタイポとして紛れ込みやすい。

-name '*.php' はクォート必須

-name *.php のようにクォートを外して書くと、動く時と動かない時がある。

$ find app -name *.php -type f | sort | xargs wc -l

*.php はfindに渡る前に、シェルがfindを実行しているカレントディレクトリでglob展開しようとする。

  • カレントディレクトリに *.php にマッチするファイルが無ければ、bashは展開できずパターンをそのままリテラル文字列として渡す。結果的に意図通りに動く。
  • カレントディレクトリに *.php にマッチするファイルがあれば、シェルがそれを展開してしまい、findに渡る -name の引数がすり替わる。

実際に、カレントディレクトリに test.php を1つ置いた状態で同じコマンドを実行したら、app/ 配下の .php ファイルが1件もヒットせず 0 になった。シェルが *.php を test.php に展開してしまい、-name test.php として実行された形。

-name にglobを渡すときは常にクォートしておくのが安全。

$ find app -name '*.php' -type f | sort | xargs wc -l