How do I count all the files recursively through directories

I want to see how many files are in subdirectories to find out where all the inode usage is on the system. Kind of like I would do this for space usage

du -sh /*

which will give me the space used in the directories off of root, but in this case I want the number of files, not the size.

Asked By: xenoterracide

||

Try:

find /path/to/start/at -type f -print | wc -l

as a starting point, or if you really only want to recurse through the subdirectories of a directory (and skip the files in that top level directory)

find `find /path/to/start/at -mindepth 1 -maxdepth 1 -type d -print` -type f -print | wc -l
Answered By: Cry Havok

Give this a try:

find -type d -print0 | xargs -0 -I {} sh -c 'printf "%st%sn" "$(find "{}" -maxdepth 1 -type f | wc -l)" "{}"'

It should work fine unless filenames include newlines.

Answered By: Dennis Williamson
find . -maxdepth 1 -type d | while read -r dir
do printf "%s:t" "$dir"; find "$dir" -type f | wc -l; done

Thanks to Gilles and xenoterracide for safety/compatibility fixes.

The first part: find . -maxdepth 1 -type d will return a list of all directories in the current working directory. 
(Warning: -maxdepth is a GNU extension
and might not be present in non-GNU versions of find.) 
This is piped to…

The second part: while read -r dir; do
(shown above as while read -r dir(newline)do) begins a while loop – as long as the pipe coming into the while is open (which is until the entire list of directories is sent), the read command will place the next line into the variable dir. Then it continues…

The third part: printf "%s:t" "$dir" will print the string in $dir
(which is holding one of the directory names) followed by a colon and a tab
(but not a newline).

The fourth part: find "$dir" -type f makes a list of all the files
inside the directory whose name is held in $dir. This list is sent to…

The fifth part: wc -l counts the number of lines that are sent into its standard input.

The final part: done simply ends the while loop.

So we get a list of all the directories in the current directory. For each of those directories, we generate a list of all the files in it so that we can count them all using wc -l. The result will look like:

./dir1: 234
./dir2: 11
./dir3: 2199
...
Answered By: Shawn J. Goff

The following solution counts the actual number of used inodes starting from current directory:

find . -print0 | xargs -0 -n 1 ls -id | cut -d' ' -f1 | sort -u | wc -l

To get the number of files of the same subset, use:

find . | wc -l

For solutions exploring only subdirectories, without taking into account files in current directory, you can refer to other answers.

Answered By: mouviciel

Here’s a compilation of some useful listing commands (re-hashed based on previous users code):

List folders with file count:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" -type f | wc -l); printf "%4d : %sn" $n "$dir"; done

List folders with non-zero file count:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" -type f | wc -l); if [ $n -gt 0 ]; then printf "%4d : %sn" $n "$dir"; fi; done

List folders with sub-folder count:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" -type d | wc -l); let n--; printf "%4d : %sn" $n "$dir"; done

List folders with non-zero sub-folder count:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" -type d | wc -l); let n--; if [ $n -gt 0 ]; then printf "%4d : %sn" $n "$dir"; fi; done

List empty folders:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" | wc -l); let n--; if [ $n -eq 0 ]; then printf "%4d : %sn" $n "$dir"; fi; done

List non-empty folders with content count:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" | wc -l); let n--; if [ $n -gt 0 ]; then printf "%4d : %sn" $n "$dir"; fi; done
Answered By: DolphinDream

Try find . -type f | wc -l, it will count of all the files in the current directory as well as all the files in subdirectories. Note that all directories will not be counted as files, only ordinary files do.

Answered By: herohuyongtao

OS X 10.6 chokes on the command in the accepted answer, because it doesn’t specify a path for find. Instead use:

find . -maxdepth 1 -type d | while read -r dir; do printf "%s:t" "$dir"; find "$dir" -type f | wc -l; done
Answered By: abeboparebop

I know I’m late to the party, but I believe this pure bash (or other shell which accept double star glob) solution could be much faster in some situations:

shopt -s globstar    # to enable ** glob in bash
for dir in */; do a=( "$dir"/**/* ); printf "%st%sn" "$dir:" "${#a[*]}"; done

output:

d1/:    302
d2/:    24
d3/:    640
...
Answered By: jimmij

If you have ncdu installed (a must-have when you want to do some cleanup), simply type c to "Toggle display of child item counts". And C to "Sort by items".

Answered By: Demi-Lune

du –inodes

I’m not sure why no one (myself included) was aware of:

du --inodes
--inodes
      list inode usage information instead of block usage

I’m pretty sure this solves the OP’s problem. I’ve started using it a lot to find out where all the junk in my huge drives is (and offload it to an older disk).

Further info

If you DON’T want to recurse (which can be useful in other situations), add

-S, --separate-dirs
Answered By: Sridhar Sarnobat

Use this recursive function to list total files in a directory recursively, up to a certain depth (it counts files and directories from all depths, but show print total count up to the max_depth):

#!/bin/bash
# set -x

export max_depth="2"
export found_files="/tmp/found_files.txt"

function get_all_the_files()
{
    depth="$1";
    base_directory="$2";

    if [[ "$depth" -ge "$max_depth" ]];
    then
        return;
    fi

    find "$base_directory" -maxdepth 1 -type d | while read -r inner_directory
    do
        printf "%st%sn" "$(find "$inner_directory" | wc -l)" "$inner_directory" | tee -a "$found_files";
        if [[ "w$(realpath "$base_directory")" != "w$(realpath "$inner_directory")" ]];
        then
            get_all_the_files "$(( depth + 1 ))" "$inner_directory";
        fi;
    done;
}

rm -f "$found_files"
get_all_the_files 0 /tmp/

printf 'nFinished searching files, sorting all:n'
sort --version-sort "$found_files"
Answered By: user

Inside the folder (directory) you want to count (cd /my/dir) you can do the following:

  1. To count all folders and files:
    find . | wc -l
  2. To count only folders (directories):
    find . -type d | wc -l
  3. To count only files:
    find . -type f | wc -l

This way you are able to verify that: folders (2) + files (3) = total (1)


Some explanation:

  • The command find . will print each of all the folders (directories) and files line by line.
    • The parameter: -type d says to print only directories (folders)
    • The parameter: -type f says to print only files.
  • The command wc -l should mean something like: word count with the parameter: lines.
Answered By: Guilherme Abacherli
Categories: Answers Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.