I'm writing a script that outputs a bar graph of the sizes of the files/directories in a directory. I'm currently getting the required data with the line
array=($(du -sc * | sort -hr))
which results in every other line of array
being a size and every other line a filename corresponding to it. However, if any of the filenames contain spaces, this naive approach doesn't work because the output is split at every space.
Basically what I want to do is parse the output line by line so that from each line I first get the characters up to the first space (the size), and then the rest of the line (the filename, which may or may not contain spaces). I thought about alternating the IFS between a space and a newline, but couldn't think of how exactly I would do that.
I'd prefer the solution to be portable between different shells, or at least to work in ksh.
The way to read line by line is a while read
loop, and read
allows reading multiple fields:
names=() sizes=()
while read -r size name
do
echo "The file '$name' has size $size"
names+=("$name")
sizes+=("$size")
done < <(du -sc ./* | sort -hr)
The ./*
prevents problems with files starting with dashes (for du
) and leading spaces (for read
).