# Making a disk usage breakdown

I'm looking for a better way of doing this code I made. I work for tech support and one of the biggest questions I am asked is: "Hey, how did my disk get so full in my VPS?"

I am aiming for output like:

home/ is taking up xGB
home/user1 xgb
home/user2 xgb


and so on. So far I have this, which does alright, but I am looking for a prettier way of getting this done.

#!/bin/bash
for i in $(ls -d */ | grep -v proc); do printf "****$i has the following breakdown ********\n"

du -h --max-depth=1 $i done  • Even after you narrow it down to a specific user, you would still need to investigate that home directory. Have you used ncdu? – 200_success Jul 24 '18 at 23:49 • yeeeee ncdu is alright... but doesn't script in too well... It's fine for me, being on my end, but I am trying to break it down dummy style for a customer that literally doesn't want to do anything. lol so my goal is to get the breakdown to look pretty and send it to the customer in a pretty pink bow – Charles Wilson Jul 25 '18 at 0:16 ## 1 Answer # Use 'shellcheck' to spot common problems 200236.sh:2:12: warning: Don't use ls | grep. Use a glob or a for loop with a condition to allow non-alphanumeric filenames. [SC2010] 200236.sh:2:18: note: Use ./*glob* or -- *glob* so names with dashes won't become options. [SC2035] 200236.sh:4:8: note: Don't use variables in the printf format string. Use printf "..%s.." "$foo". [SC2059]
200236.sh:4:53: note: Backslash is literal in "\n". Prefer explicit escaping: "\\n". [SC1117]
200236.sh:6:21: note: Double quote to prevent globbing and word splitting. [SC2086]


# Don't parse the output of ls

The ls program works well for interactive use, but isn't designed to be parsed by scripts. The main problem is that whitespace and other shell-significant characters are shown as-is, with no quoting. You could try to work around this using ls -b, but it's more robust to avoid the problem altogether:

for i in */
do
if [[ i =~ proc ]]; then continue; fi
# ...
done


# The test for virtual filesystems is too broad

grep proc will pick up names such as processor - do you really want to exclude them? If you want to avoid inspecting filesystems not backed by disks, there are more reliable means:

case $(stat --file-system --format '%T' "$i") in
proc|tmpfs|sysfs) continue ;;
esac


du -h --max-depth=1 "$i" # ^^^^  # Don't expand parameters into a format string Use echo or printf, but don't confuse the two ($i may contain %):

echo "**** $i has the following breakdown ********"  printf '**** %s has the following breakdown ********\n' "$i"


# Constrain du to a single filesystem

I'm not sure whether or not you want du to cross mountpoints. If not, then add -x / --one-file-system to its options.

# Modified code

#!/bin/bash
for i in */
do
case $(stat --file-system --format '%T' "$i") in
proc|tmpfs|sysfs) continue ;;
esac

echo "**** $i has the following breakdown ********" du -h --one-file-system --max-depth=1 "$i"
done

• WOAH!!!!! Implementing testing and thank you so much! @toby This wasn't just an answer it was knowledge and I appreciate it. ALOT – Charles Wilson Jul 26 '18 at 3:44