JP / EN

広告
2023/03/27

コマンドでファイルやディレクトリ数を数える:ls + grep + wcで条件を指定

タグ:linux

コマンドで特定のポイント以下のファイルやディレクトリの数を 数えたいことがしばしばある。
単純にはlsでプリントしてから手で数えたら良いが、 ファイルが何千、何万もあるとそうもいかない。
そこで
  • ls: ファイルやディレクトリを列挙
  • grep: 入力から条件を満たす行を抽出
  • wc: 入力の行数などを数える
を組み合わせることでファイル・ディレクトリ数を自動で数えよう。

実行例

基本:カレントディレクトリ直下のファイルとディレクトリを数える

単純にすべてのカレントディレクトリ直下のファイル+ディレクトリを数えるには lsもwcもほぼそのまま使える。wcの-lオプションは行数カウントのみ出力する、出力整形用の オプションでカウントの動作には関係ない。
また古い資料だとlsの出力を1行ずつ改行する-1オプションが必須と書いてあるのももあるが、 私の環境だとあってもなくても出力が変わらなかった(バージョンの関係か?)。
    # 練習用ディレクトリをプリント
    $ tree
    .
    ├── dir1
    │   └── subfile1.txt
    ├── dir2
    │   ├── dir3
    │   │   └── subfile3.txt
    │   └── subfile2.txt
    ├── file1.txt
    ├── file2.txt
    ├── file3.txt
    └── file4.csv

    # カレント直下は6つ
    $ ls
    dir1  dir2  file1.txt  file2.txt  file3.txt  file4.csv

    $ ls | wc -l
    6
  


カレントディレクトリ直下のファイルのみ/ディレクトリのみを数える

ファイルのみ・ディレクトリのみに絞りたいときはlsの-Fをつける。 これにより名前の後にタイプ識別子(ファイルなら*、ディレクトリなら/)を つけてくれるので、見分けられるようになる。
そのうえでgrepでフィルタリングする。
    # 練習用ディレクトリをプリント
    # -Fオプションでファイル・ディレクトリの表示分け
    $ ls -F
    dir1/  dir2/  file1.txt*  file2.txt*  file3.txt*  file4.csv*

    $  ls -F | grep "*"
    file1.txt*
    file2.txt*
    file3.txt*
    file4.csv*
    $  ls -F | grep "*" | wc -l
    4
    
    $  ls -F | grep "/"
    dir1/
    dir2/
    $  ls -F | grep "/" | wc -l
    2
  


再帰的にサブディレクトリ以下まで数える

lsはデフォルトだとカレント直下しか見ないので、再帰のオプション-Rを つける。なお再帰時には"[directory]/:"のように見に行ったディレクトリを 途中で表示してしまい、ナイーブにやるとこれで数のずれが生じる。また空白行もでる。grepで うまくこれらを除外する必要がある。grepの-vオプションを使い":"と"^$" (これが空白行を表す正規表現になる) を除外しよう。
    $ ls -1R
    .:
    dir1
    dir2
    file1.txt
    file2.txt
    file3.txt
    file4.csv

    ./dir1:
    subfile1.txt

    ./dir2:
    dir3
    subfile2.txt

    ./dir2/dir3:
    subfile3.txt

    $ ls -1R | grep -ve ":" -e "^$"
    dir1
    dir2
    file1.txt
    file2.txt
    file3.txt
    file4.csv
    subfile1.txt
    dir3
    subfile2.txt
    subfile3.txt

    $ ls -1R | grep -ve ":" -e "^$" | wc -l
    10
  

特定のディレクトリ・ファイルだけ除外する

grepの-vオプションで除外するパターンの設定ができるので、 これをうまく使う。
なおlsだとどうやっても再帰的にフルパスでの表示はできないので、サブディレクトリ名で除外をかけたいときなど できないケースがあると分かった。そのようなときはlsの代わりにfindを使おう。 こちらはデフォルトで途中のディレクトリも表示してくれるので、除外が簡単である。なお findではカレントディレクトリ"."が出力行に含まれてしまうので、合計から-1することを忘れないようにする。
実験として"dir2"以下のディレクトリ・ファイルのみ計数から除外してみる。
    $ find
    .
    ./dir1
    ./dir1/subfile1.txt
    ./dir2
    ./dir2/dir3
    ./dir2/dir3/subfile3.txt
    ./dir2/subfile2.txt
    ./file1.txt
    ./file2.txt
    ./file3.txt
    ./file4.csv

    $ find | grep -v dir3
    .
    ./dir1
    ./dir1/subfile1.txt
    ./dir2
    ./dir2/subfile2.txt
    ./file1.txt
    ./file2.txt
    ./file3.txt

    $ find | grep -v dir3 | wc -l
    9
  




このエントリーをはてなブックマークに追加

https://wonderhorn.net/