[linux] How to count number of files in each directory?

I am able to list all the directories by

find ./ -type d

I attempted to list the contents of each directory and count the number of files in each directory by using the following command

find ./ -type d | xargs ls -l | wc -l

But this summed the total number of lines returned by

find ./ -type d | xargs ls -l

Is there a way I can count the number of files in each directory?

This question is related to linux bash ubuntu

The answer is


This will give the overall count.

for file in */; do echo "$file -> $(ls $file | wc -l)"; done | cut -d ' ' -f 3| py --ji -l 'numpy.sum(l)'

Slightly modified version of Sebastian's answer using find instead of du (to exclude file-size-related overhead that du has to perform and that is never used):

 find ./ -mindepth 2 -type f | cut -d/ -f2 | sort | uniq -c | sort -nr

-mindepth 2 parameter is used to exclude files in current directory. If you remove it, you'll see a bunch of lines like the following:

  234 dir1
  123 dir2
    1 file1
    1 file2
    1 file3
      ...
    1 fileN

(much like the du-based variant does)

If you do need to count the files in current directory as well, use this enhanced version:

{ find ./ -mindepth 2 -type f | cut -d/ -f2 | sort && find ./ -maxdepth 1 -type f | cut -d/ -f1; } | uniq -c | sort -nr

The output will be like the following:

  234 dir1
  123 dir2
   42 .

You could arrange to find all the files, remove the file names, leaving you a line containing just the directory name for each file, and then count the number of times each directory appears:

find . -type f |
sed 's%/[^/]*$%%' |
sort |
uniq -c

The only gotcha in this is if you have any file names or directory names containing a newline character, which is fairly unlikely. If you really have to worry about newlines in file names or directory names, I suggest you find them, and fix them so they don't contain newlines (and quietly persuade the guilty party of the error of their ways).


If you're interested in the count of the files in each sub-directory of the current directory, counting any files in any sub-directories along with the files in the immediate sub-directory, then I'd adapt the sed command to print only the top-level directory:

find . -type f |
sed -e 's%^\(\./[^/]*/\).*$%\1%' -e 's%^\.\/[^/]*$%./%' |
sort |
uniq -c

The first pattern captures the start of the name, the dot, the slash, the name up to the next slash and the slash, and replaces the line with just the first part, so:

./dir1/dir2/file1

is replaced by

./dir1/

The second replace captures the files directly in the current directory; they don't have a slash at the end, and those are replace by ./. The sort and count then works on just the number of names.


I tried with some of the others here but ended up with subfolders included in the file count when I only wanted the files. This prints ./folder/path<tab>nnn with the number of files, not including subfolders, for each subfolder in the current folder.

for d in `find . -type d -print` 
do 
  echo -e "$d\t$(find $d -maxdepth 1 -type f -print | wc -l)"
done

THis could be another way to browse through the directory structures and provide depth results.

find . -type d  | awk '{print "echo -n \""$0"  \";ls -l "$0" | grep -v total | wc -l" }' | sh 

This can also be done with looping over ls instead of find

for f in */; do echo "$f -> $(ls $f | wc -l)"; done

Explanation:

for f in */; - loop over all directories

do echo "$f -> - print out each directory name

$(ls $f | wc -l) - call ls for this directory and count lines


This should return the directory name followed by the number of files in the directory.

findfiles() {
    echo "$1" $(find "$1" -maxdepth 1 -type f | wc -l)
}

export -f findfiles

find ./ -type d -exec bash -c 'findfiles "$0"' {} \;

Example output:

./ 6
./foo 1
./foo/bar 2
./foo/bar/bazzz 0
./foo/bar/baz 4
./src 4

The export -f is required because the -exec argument of find does not allow executing a bash function unless you invoke bash explicitly, and you need to export the function defined in the current scope to the new shell explicitly.


A super fast miracle command, which recursively traverses files to count the number of images in a directory and organize the output by image extension:

find . -type f | sed -e 's/.*\.//' | sort | uniq -c | sort -n | grep -Ei '(tiff|bmp|jpeg|jpg|png|gif)$'

Credits: https://unix.stackexchange.com/a/386135/354980


find . -type f -printf '%h\n' | sort | uniq -c

gives for example:

  5 .
  4 ./aln
  5 ./aln/iq
  4 ./bs
  4 ./ft
  6 ./hot

Easy way to recursively find files of a given type. In this case, .jpg files for all folders in current directory:

find . -name *.jpg -print | wc -l


I edited the script in order to exclude all node_modules directories inside the analyzed one.

This can be used to check if the project number of files is exceeding the maximum number that the file watcher can handle.

find . -type d ! -path "*node_modules*" -print0 | while read -d '' -r dir; do
    files=("$dir"/*)
    printf "%5d files in directory %s\n" "${#files[@]}" "$dir"
done

To check the maximum files that your system can watch:

cat /proc/sys/fs/inotify/max_user_watches

node_modules folder should be added to your IDE/editor excluded paths in slow systems, and the other files count shouldn't ideally exceed the maximum (which can be changed though).


find . -type f | cut -d/ -f2 | sort | uniq -c
  • find. -type f to find all items of the type file
  • cut -d/ -f2 to cut out their specific folder
  • sort to sort the list of foldernames
  • uniq -c to return the number of times each foldername has been counted

Everyone else's solution has one drawback or another.

find -type d -readable -exec sh -c 'printf "%s " "$1"; ls -1UA "$1" | wc -l' sh {} ';'

Explanation:

  • -type d: we're interested in directories.
  • -readable: We only want them if it's possible to list the files in them. Note that find will still emit an error when it tries to search for more directories in them, but this prevents calling -exec for them.
  • -exec sh -c BLAH sh {} ';': for each directory, run this script fragment, with $0 set to sh and $1 set to the filename.
  • printf "%s " "$1": portably and minimally print the directory name, followed by only a space, not a newline.
  • ls -1UA: list the files, one per line, in directory order (to avoid stalling the pipe), excluding only the special directories . and ..
  • wc -l: count the lines

Here's one way to do it, but probably not the most efficient.

find -type d -print0 | xargs -0 -n1 bash -c 'echo -n "$1:"; ls -1 "$1" | wc -l' --

Gives output like this, with directory name followed by count of entries in that directory. Note that the output count will also include directory entries which may not be what you want.

./c/fa/l:0
./a:4
./a/c:0
./a/a:1
./a/a/b:0

I combined @glenn jackman's answer and @pcarvalho's answer(in comment list, there is something wrong with pcarvalho's answer because the extra style control function of character '`'(backtick)).

My script can accept path as an augument and sort the directory list as ls -l, also it can handles the problem of "space in file name".

#!/bin/bash
OLD_IFS="$IFS"
IFS=$'\n'
for dir in $(find $1 -maxdepth 1 -type d | sort); 
do
    files=("$dir"/*)
    printf "%5d,%s\n" "${#files[@]}" "$dir"
done
FS="$OLD_IFS"

My first answer in stackoverflow, and I hope it can help someone ^_^


This prints the file count per directory for the current directory level:

du -a | cut -d/ -f2 | sort | uniq -c | sort -nr

Examples related to linux

grep's at sign caught as whitespace How to prevent Google Colab from disconnecting? "E: Unable to locate package python-pip" on Ubuntu 18.04 How to upgrade Python version to 3.7? Install Qt on Ubuntu Get first line of a shell command's output Cannot connect to the Docker daemon at unix:/var/run/docker.sock. Is the docker daemon running? Run bash command on jenkins pipeline How to uninstall an older PHP version from centOS7 How to update-alternatives to Python 3 without breaking apt?

Examples related to bash

Comparing a variable with a string python not working when redirecting from bash script Zipping a file in bash fails How do I prevent Conda from activating the base environment by default? Get first line of a shell command's output Fixing a systemd service 203/EXEC failure (no such file or directory) /bin/sh: apt-get: not found VSCode Change Default Terminal Run bash command on jenkins pipeline How to check if the docker engine and a docker container are running? How to switch Python versions in Terminal?

Examples related to ubuntu

grep's at sign caught as whitespace "E: Unable to locate package python-pip" on Ubuntu 18.04 How to Install pip for python 3.7 on Ubuntu 18? "Repository does not have a release file" error ping: google.com: Temporary failure in name resolution How to install JDK 11 under Ubuntu? How to upgrade Python version to 3.7? Issue in installing php7.2-mcrypt Install Qt on Ubuntu Failed to start mongod.service: Unit mongod.service not found