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.
for i in $(ls -d */ | grep -v proc); do printf "**** $i has the following breakdown ********n" du -h --max-depth=1 $i done
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 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
Always quote parameter expansions
du -h --max-depth=1 "$i" # ^^^^
Don’t expand parameters into a format string
printf, but don’t confuse the two (
$i may contain
echo "**** $i has the following breakdown ********"
printf '**** %s has the following breakdown ********n' "$i"
du to a single filesystem
I’m not sure whether or not you want
du to cross mountpoints. If not, then add
--one-file-system to its options.
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