List a directory, including subdirectories, with file count and cumulative size

command linedisk-usagels

Is there a way to list out the content of a directory including subdirectories with a file count and cumulative size?

I would like to see:

  • Number of directories
  • Number of sub directories
  • number of files
  • cumulative size

Best Answer

If I understand you correctly, this will give you want you want:

find /path/to/target -type d | while IFS= read -r dir; do 
  echo -ne "$dir\tsize: $(du -sh "$dir" | cut -f 1)" 
  echo -ne "\tsubdirs: $(find "$dir" -mindepth 1 -type d | wc -l)"
  echo -e "\tfiles: $(find "$dir" -type f | wc -l )";
done  | tac

If you run this on /boot for example, you get output like this:

/boot/burg/themes/sora_extended size: 8.0K  subdirs: 0  files: 1
/boot/burg/themes/radiance/images   size: 196K  subdirs: 0  files: 48
/boot/burg/themes/radiance  size: 772K  subdirs: 1  files: 53
/boot/burg/themes/winter    size: 808K  subdirs: 0  files: 35
/boot/burg/themes/icons size: 712K  subdirs: 0  files: 76
/boot/burg/themes   size: 8.9M  subdirs: 26 files: 440
/boot/burg/fonts    size: 7.1M  subdirs: 0  files: 74
/boot/burg  size: 20M   subdirs: 29 files: 733
/boot/grub/locale   size: 652K  subdirs: 0  files: 17
/boot/grub  size: 4.6M  subdirs: 1  files: 224
/boot/extlinux/themes/debian-wheezy/extlinux    size: 732K  subdirs: 0  files: 11
/boot/extlinux/themes/debian-wheezy size: 1.5M  subdirs: 1  files: 22
/boot/extlinux/themes   size: 1.5M  subdirs: 2  files: 22
/boot/extlinux  size: 1.6M  subdirs: 3  files: 28
/boot/  size: 122M  subdirs: 36 files: 1004

To have easy access to this command, you could turn it into a function. Add these lines to your shell's initialization file (~/.bashrc for bash):

dirsize(){
    find "$1" -type d | while IFS= read -r dir; do 
    echo -ne "$dir\tsize: $(du -sh "$dir"| cut -f 1)" 
    echo -ne "\tsubdirs: $(find "$dir" -mindepth 1 -type d | wc -l)"
    echo -e "\tfiles: $(find "$dir" -maxdepth 1 -type f | wc -l )";
    done  | tac
}

You can now run it as dirsize /path/.


Explanation

The function above has 5 major parts:

  1. find /path/to/target -type d | while IFS= read -r dir; do ... ; done : This will find all directories under /path/to/target and process each of them by setting the variable dir to their name. The IFS= ensures this won't break on directories with spaces in their names.

  2. echo -ne "$dir\tsize: $(du -sh "$dir" | cut -f 1)" : This uses the command du to get the directory's size and cut to print only the first field of du.

  3. echo -ne "\tsubdirs: $(find "$dir" -mindepth 1 -type d | wc -l)" : This find command looks for subdirectories of $dir. The type -d ensures we only find directories, no files and the -mindepth makes sure we do not count the current directory, ..

  4. echo -e "\tfiles: $(find "$dir" -maxdepth 1 -type f | wc -l)"; : This one looks for files (-type f) that are directly (-maxdepth 1) under $dir. It will not count files that are in subdirectories of $d.

  5. | tac : Finally, the whole thing is passed through tac which simply reverses the order in which lines are printed. This means that the total size of the target directory will be shown as the last line. If that is not what you want, simply delete | tac.

Related Question