We already know how to Show number of files in a single directory tree using Shell, but what if given a directory, we would like to know the number of files in each one of its subdirectories separately?
We assume the same directory structure as in that other article:
groups/
all.txt
people/
John.txt
Jane.txt
maskots/
Foo.txt
Bar.txt
other -> maskots
In the previous article we reached this solution for a single directory:
$ find groups -type f | wc -l
Now we need to go over all the subdirectories and run the above expression for each one of them.
Wildecard expansion
In our first attempt we use the wildecard expansion groups/*
to list all the
item in the "groups" directory. We go over it in a for
loop and for each iteration
we echo the name of the thing and call the above expression.
$ for x in groups/*; do (echo $x; find $x -type f | wc -l) ; done
groups/all.txt
1
groups/maskots
2
groups/other
0
groups/people
2
The output includes the directories 'maskots' and 'people' as we wanted, but it also includes "all.txt" which is a plain file and 'other' which is a symbolic link.
Find with backtick
We can use find
here too with type
directory and maxdepth
1,
but that will return the root directory as well:
$ find groups -maxdepth 1 -type d
groups
groups/maskots
groups/people
In this case we can also include mindepth
to make sure only the right depth is included:
$ find groups -maxdepth 1 -mindepth 1 -type d
groups/maskots
groups/people
Using this we can now write:
$ for x in `find groups -maxdepth 1 -mindepth 1 -type d`; do (echo $x; find $x -type f | wc -l) ; done
groups/maskots
2
groups/people
2
Using result interpolation
Instead of the backticks ````, it is usually better to write $()
.
The result is the same:
$ for x in $(find groups -maxdepth 1 -mindepth 1 -type d ); do (echo $x; find $x -type f | wc -l) ; done
groups/maskots
2
groups/people
2