I want to make a bash function that would behave just like how wc -l
behaves on multiple files to count their number of lines in counting the number of files in a set of directories.
How wc -l
works:
wc -l test.zip tt.zip zzz.zip | sort
17 tt.zip
2015 test.zip
6567 zzz.zip
8599 total
How I want my function to work on files:
count dir1 dir2 dir3 | sort:
1 dir1
144 dir2
1000 dir3
1145 total
Where dir{1..3} are 3 directories and the number of files shown includes the hidden files.
What I've already done:
#/bin/bash
count() {
if [ "`file -b $1`" == 'directory' ] ; then
echo `la "$1" | wc -l`
else
wc -l "$@" | sort
fi
}
I can implement it with a for loop on $@
but I'd rather find an easier solution.
If you can also help me include the size of each directory. You would make me really happy!
Try:
If the directories are specified in
$@
, then use:How it works
find dir1 dir2 dir3 -maxdepth 1 -type f -printf '%h\n'
This looks for all regular files in directories dir1, dir2, and dir3. For each file found, its directory is printed.
-maxdepth 1
(optional) tells find not to dive into subdirectories.-type f
tells find to only report on regular files. For each file found,-printf '%h\n'
tells find to print the directory that the file is in.awk '{c[$0]++} END{for (dir in c) printf "%6i %s\n",c[dir],dir}'
This counts the number of times each directory appears on the input. After all the input has been read, it prints the totals.
We use associative array
c
to count the number of times each directory is seen. In awk,$0
is the contents of the current line being read.c[$0]
is the number of times that line has been seen so far.c[$0]++
increments that count by one.sort -n
This sorts the output in ascending order of file count. (
-n
tells sort to sort numerically rather than alphabetically.)Example
Let's suppose that we have these directories with these files:
Our command produces the output:
Improvement: Adding a total row
To suppress the printing of TOTAL if there is only one directory in the output:
Include empty directories in the output
To also include empty directories:
As an example, let's consider an empty directory:
And, let's set
$@
:Now, let's run our code:
Let's try again with two directories: