6

I came up with the following snippet for counting files in each subdirectory:

for x (**/*(/)); do print $x; find $x -maxdepth 1 -type f | wc -l; done

The command outputs consecutive pairs (one below the other) as follows:

directory_name
# of files

I would like to change the code above to:

  • Print each match on the same line (i.e. directory_name ':' # of files)
  • Only count files if the folders are leaves in the directory tree (i.e. they don't have any subfolders).

How can I do that?

2 Answers2

4

try this:

for dir in $( gfind . -type d -print ); do files=$( find $dir -maxdepth 1 -type f | wc -l ); echo "$dir : $files"; done

or, in a script, where you can have a bit more flexibility:

#!/usr/bin/ksh

# pass in the directory to search on the command line, use $PWD if not arg received
rdir=${1:-$(pwd)}

# if $rdir is a file, get it's directory
if [ -f $rdir ]; then
    rdir=$(dirname $rdir)
fi

# first, find our tree of directories
for dir in $( gfind $rdir -type d -print ); do
    # get a count of directories within $dir.
    sdirs=$( find $dir -maxdepth 1 -type d | wc -l );
    # only proceed if sdirs is less than 2 ( 1 = self ).
    if (( $sdirs < 2 )); then 
        # get a count of all the files in $dir, but not in subdirs of $dir)
        files=$( find $dir -maxdepth 1 -type f | wc -l ); 
        echo "$dir : $files"; 
    fi
done

I use ksh for shell scripts, but it works just as well with #!/usr/bin/zsh, or /usr/bin/bash.

Tim Kennedy
  • 19,697
  • 1
    find. some systems (like Solaris) which use their own implementation of find, make the GNU tools available by prefixing them with a g. as in, gfind, gmake, gfind, etc. For use on Linux, or other which default to GNU versions of tools, simply change gfind to find. – Tim Kennedy Oct 18 '11 at 03:18
  • Thanks @Tim. Does the script above count files only on those folders that are leaves of the directory tree? (i.e. folders that don't have any subfolders)? It looks like it counts the files on every subfolder. – Amelio Vazquez-Reina Oct 18 '11 at 15:06
  • @intrpc, ah, sorry. i was printing totals for all files, by directory. I've edited it to only print the count of files only for directories that do not themselves include another directory. – Tim Kennedy Oct 18 '11 at 21:13
4

quick 'n' dirty

find . -type d | \
while IFS= read -r d; do
    f=$(ls -F "$d");
    echo "$f" | egrep -q "/$" || \
        echo $d : $(echo -n "$f"|wc -l) files;
done
forcefsck
  • 7,964
  • very nice! way more elegant than mine, and gives exactly the same output ( if you just swap find . -type d with find ${1:-$(pwd)} -type d ). – Tim Kennedy Oct 19 '11 at 17:29
  • 1
    @TimKennedy, thanks. It's not a script though, just a one-liner, that's why $1 is not taken in to account. – forcefsck Oct 20 '11 at 08:00