Linuxでディレクトリ内のファイル数を効率的にカウントするテクニック

Linuxでファイル数を数えるときは、まず「直下だけか、サブディレクトリも含むか」「通常ファイルだけか、ディレクトリやリンクも含むか」を決めます。GNU findでは、一致した項目ごとに1文字を出力し、wc -cで数えると、改行を含むファイル名でも件数を誤りにくくなります。

この記事のコマンドはGNU findutils・GNU coreutilsのあるLinux向けです。macOS標準のfindやBusyBoxでは、-printfなどに対応していない場合があります。設定変更やファイル削除は行いませんが、権限のない場所や更新中のディレクトリでは結果に制約があります。

目次

最初に対象ディレクトリへ移動する

以下の/path/to/directoryを実際のパスへ置き換えます。空白を含むパスにも対応するよう引用符で囲みます。移動に失敗したら、その後のfindを実行しないでください。ここで選んだディレクトリを、以降の例では「.」で表します。

cd -- "/path/to/directory" && pwd

最初のcdの成功を確認してからpwdで対象を確認します。シェルスクリプトでは後述のように、失敗時の終了を明示します。別の場所で実行してしまうと、正しいコマンドでも目的とは違う件数になります。

直下の通常ファイルだけを数える

find . -maxdepth 1 -type f -printf '.' | wc -c

-maxdepth 1で直下までに限定し、-type fで通常ファイルを選びます。ディレクトリやシンボリックリンクは含めません。ドットで始まる隠しファイルも対象です。-printfの「.」はパスではなく、1件につき出力する1バイトの文字であり、wc -cがそのバイト数を数えます。

この短いパイプラインは対話的な確認用です。途中でPermission deniedなどが出た場合、表示された数を全件数として採用しないでください。自動処理では、後述の失敗を検知するスクリプトを使用します。

サブディレクトリを含めて数える

find . -type f -printf '.' | wc -c

-maxdepthを外すと、配下のディレクトリを再帰的にたどります。隠しディレクトリの中も検索しますが、既定ではシンボリックリンク先をたどりません。ハードリンクが複数のパスとして現れる場合は各パスを1件ずつ数えるため、「重複のないinode数」とは異なります。

拡張子・種類・範囲で絞り込む

.txtファイルだけを数える

find . -type f -name '*.txt' -printf '.' | wc -c

*.txtは引用符で囲み、シェルではなくfindにパターンを渡します。-nameは大文字と小文字を区別するため、.TXTも含めたい場合は-inameに替えます。先頭がドットのファイルも、名前が条件に合えば対象です。

直下の全項目を数える

find . -mindepth 1 -maxdepth 1 -printf '.' | wc -c

通常ファイル、ディレクトリ、シンボリックリンクなどを区別せず、直下の項目を数えます。-mindepth 1は検索の起点「.」自体を除外するための指定です。隠し項目も含むので、通常のlsの見た目の件数とは異なることがあります。

サブディレクトリだけを数える

find . -mindepth 1 -type d -printf '.' | wc -c

起点を除いた配下のディレクトリ数です。直下だけに限定したい場合は-maxdepth 1も追加します。シンボリックリンク自体の数を調べるなら、既定のリンクをたどらない動作のまま-type lを指定します。

ls | wc -lやfind | wc -lを使う際の落とし穴

ls -1 | wc -l
find . -type f | wc -l

これらは一覧の行数を数えています。Linuxのファイル名には改行を含められるため、1つのファイルが複数行になると正確な件数ではありません。ls -1は通常、隠し項目を表示せず、通常ファイル以外も表示します。-1を付けてもこの区別は解消しません。

人が一覧を見るならlsは便利ですが、任意の名前を含む件数集計には、ファイル名そのものを出力しない-printfの方法が簡潔です。名前の一覧も後段へ渡す場合は、改行ではなくNUL区切りの-print0などに対応した処理を使います。

エラー時に部分的な件数を返さないBashスクリプト

次をcount-files.shとして保存します。引数には対象ディレクトリを1つ渡します。cdとfindの失敗を検知し、成功した場合だけ件数を表示します。現在のシェルの作業場所は変更しません。相対パスは呼び出し元の作業場所を基準にし、CDPATHによる移動先の変更や余計な出力を防ぎます。

#!/usr/bin/env bash
set -o pipefail

if [ "$#" -ne 1 ] || [ -z "${1-}" ]; then
    printf 'Usage: bash count-files.sh DIRECTORY\n' >&2
    exit 2
fi

case "$1" in
    /*) directory=$1 ;;
    *)  directory=./$1 ;;
esac

if count=$(
    unset CDPATH
    cd -P -- "$directory" >/dev/null || exit 1
    find . -type f -printf '.' | wc -c
); then
    printf 'Regular-file paths: %s\n' "$count"
else
    printf 'Count failed; do not use a partial result.\n' >&2
    exit 1
fi
bash count-files.sh "/path/to/directory"

Bashのpipefailがないと、findが失敗しても最後のwcが成功し、パイプ全体を成功とみなす場合があります。この例ではエラーを隠さず、件数が0だった場合と調査できなかった場合を区別します。-Pを付けたcdは、指定したディレクトリがリンクである場合、その移動先を作業場所として使います。配下のリンクをfindでたどる指定ではありません。

大量の項目を数える場合も全ファイル名を変数に保持する必要はありません。ただし、実行中に追加・削除が行われると、結果は単一時点の厳密なスナップショットにはなりません。バックアップや棚卸しの確定値が必要なら、更新停止や一貫性のあるスナップショットなど、運用側の条件もそろえます。

duは容量、–inodesはinode使用量を調べる

du -sh -- .
du --inodes -s -- .

du -shは主にディスク使用量を調べるコマンドで、通常ファイル数の代わりにはなりません。一方、GNU duの–inodesはinode使用量を表示できます。「duでは数に関する情報を一切得られない」という説明も正確ではありません。

–inodesはディレクトリなども対象とし、通常は同じハードリンクの実体を重複計上しません。find -type fで数える通常ファイルのパス数とは定義が違います。容量不足なのか、inode不足なのか、単に項目数を知りたいのかを分けて選んでください。

件数が合わないときの確認項目

まず直下と再帰、通常ファイルと全項目、隠し項目、リンクの扱いが同じ条件か確認します。次にエラー出力を読み、アクセスできなかったディレクトリがないか確認します。数を合わせる目的で権限を広く変更したり、無条件にsudoを付けたりしないでください。

マウントされた別ファイルシステムを検索から除外したい場合は、目的を確認してGNU findの-xdevを検討します。結果の意味が変わるため、集計の速度を上げるためだけに追加しないでください。検索時間は対象件数、ディレクトリ構成、ストレージ、キャッシュ、ネットワークなどで変わり、lsとfindの一律の速度順位はありません。

演習:ファイル名と数え方の違いを確かめる

練習用の空ディレクトリを用意し、通常ファイル2つ、隠しファイル1つ、サブディレクトリ1つとその中のファイル1つを置いて比較します。直下の通常ファイルは3件、再帰的な通常ファイルは4件、直下の全項目は4件になる構成です。実データに変更を加えず、練習用の場所だけを使います。

さらにシンボリックリンクを1つ加えた場合、直下の全項目は増えますが、既定のfind -type fにはそのリンク自体を含めません。隠し項目やリンクを含む条件を記録すると、別の人が同じ集計を再現しやすくなります。

まとめ

通常ファイルの数を知りたいときは、GNU findの-type fと-printf、wc -cを組み合わせます。直下だけなら-maxdepth 1を加え、全項目なら起点を除く-mindepth 1も使います。エラー、更新中のデータ、リンク、inodeの違いを確認してから結果を利用しましょう。

参考資料

GNU find:-printf/検索の深さと範囲/ファイル種別/シンボリックリンク。

特殊な文字を含むファイル名/GNU coreutils:du・wc/Bashのパイプラインと終了状態。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次