Score:-2

Getting the total size of my five largest files in bash

lr flag

I am trying to get the total size of my five largest files found in a directory but I am not getting du to work on my list. I have two ways of finding and sorting, the five largest files.

#!/bin/bash

DIR=$1 #The starting directory path


if [ ! -d "$DIR" ]; then #if the directory is not found
    echo "The directory doesn't exist!" 
    exit 1
fi

echo "Five largest files using ls are:"
test_ls=$( ls -lhR "$DIR" | grep '^-' | sort -r -k 5 -h | head -n 5 )
du -ch "$test_ls"


echo "Five largest files using find/DU are:"
test_find=$( find "$DIR" -type f -exec du -ch {} + | sort -rh | head -n 5 )
du -ch "$test_find"

echo "Total number of files: "
ls -lhR "$DIR" | grep '^-' | wc -l
echo "Total size of files: "
du -sh "$DIR" | awk '{print $1}'

If I apply du on the ls variable I get :

du: invalid option -- 'r'
du: invalid option -- 'w'
du: invalid option -- '-'
du: invalid option -- 'r'

and if I apply it on the find variable I get this for each of the five files

du: cannot access '429M': No such file or directory

Both the ls version and find version works fine for listing the five largest files under the given directory, but I am relly lost in how I could add their sizes together.

hr flag
Does it have to be bash? The zsh shell for example can sort and select files by size directly ex. `du -hc **/*(.NDOL[1,5])`
Score:1
in flag

Not sure how best to fix your code, I would propose a different approach without the need for du as find can return file sizes with -printf '%s'.

Note also, that you should never parse ls and that find unlike ls will run recursively if you don't limit that with -maxdepth option.


This would find the five largest files in a directory and sum its sizes:

find "$DIR" -maxdepth 1 -type f -printf '%s\n' | sort -nr | head -n5 | paste -sd+ | bc | numfmt --to=iec
  • find ... -printf '%s\n' will print file sizes in bytes
  • | sort -nr | head -n5 will find the five largest numbers
  • | paste -sd+ will join the numbers with a plus sign in between them, so it's a mathematic expression
  • | bc will run the mathematic expression
  • | numfmt --to=iec (optional) will convert the size from bytes to human-readable format.

To get additional information, you can save find output e.g. in an array:

DIR=/some/dir
file_sizes=($(find "$DIR" -maxdepth 1 -type f -printf '%s\n' | sort -nr))

num_files=${#file_sizes[@]}
total_size=$(IFS=+; echo "$((${file_sizes[*]}))" | numfmt --to=iec)
biggest_files=$(IFS=+; echo "$((${file_sizes[*]:0:5}))" | numfmt --to=iec)

printf 'Total number of files: %d\nTotal size of files: %s\nSize of biggest 5: %s\n' $num_files $total_size $biggest_files
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.