Find the second biggest file/directory in size using commands.

What I have

du /etc/ -hsx * | sort -rh | head -2

This command shows me two lines which, by the options I've chosen, gets me the 2 biggest files/directories inside /etc/.


What if I only want to find the second biggest file? How can I do it?

Example, by doing the command sudo du /etc/ -hsx * | sort -rh | head -2 | tail -1

I get the result

1.5M snap

but what I expected is to get only it's name, not the size or else. Just the name. I've also read that can be done with the ls command too.

  • Do you want size (as reported by ls -l for instance), or disk usage (as reported by ls -s or du for instance). For directories, do you want to consider the size/disk usage of the directories, or of all the files and directories accessible through them recursively? Note that files can be referenced in more than one directory, but if you do du dir1 dir2 the size of those files referenced in both will only be accounted to dir1. Commented Nov 7, 2018 at 19:59

5 Answers 5


What if I only want to find the second biggest file? How can I do it?

Obligatory zsh option:

zsh -c 'print -r /etc/**/*(DoL[-2])'

This invokes zsh and asks it to print the argument, which is:

  • a recursive filename expansion **/*
  • sorted (ordered) by size (Length), in increasing size
  • D enables dotglob for that one glob, so also considers hidden files or files in hidden directories.
  • limited to the 2nd-to-last entry in the list ([-2])

Assuming that by size, you mean the disk usage of non-directory files or the cumulative disk usage of all the files referenced through the directory files (as your usage of du suggests), with GNU utilities, you could do:

sudo LC_ALL=C du -al0d1 /etc |
  sort -zrn |
  tail -zn+2 |
  head -zn1 |
  cut -zf2- |
  tr '\0' '\n'

The tail+head+cut can also be replaced with sed -z $'1d;s/^[^\t]*\t//;q'.


  • with du /etc/ -hsx * (which assumes GNU find and that POSIXLY_CORRECT is not in the environment as you're using options after non-option arguments), you're getting the disk usage of /etc and of all the non-hidden files in the current directory.
  • using -a and -d1 (a GNU extension) solves all the problems of * excluding hidden directories or reaching the limit of number of arguments.
  • -h is not only non-portable, but you also lose a lot of precision (so will likely make you report the wrong file), and you make sort job more difficult, so it's quite counter-productive.
  • without -l (a GNU extension), hard links are counted only once so if some-large-file is found both as /etc/dir1/some-large-file and /etc/dir2/other-link-to-some-large-file, the disk space occupied by some-large-file is only accounted to one of those directories by du.
  • newline is as valid a character as any in a file name (macOS actually used to come with file names with newline characters in /etc IIRC). So generally you can't use line-based text processing to deal with those. Most GNU utilities have -z or -0 options to work with NUL delimited records.
  • Note that in that sorted list, the first record will be for /etc. So by taking the second record, we're actually reporting the heaviest file/dir in /etc, not second-heaviest.
  • If there are ties, the file name that sorts last in the locale collation order will be chosen via the last-resort comparison done by sort without -s.

Probably one of the options would be to flip the result using sort again and use head -1? Like:

du /etc/ -hsx * | sort -rh | head -2 | sort -r | head -1

Use tail

du /etc/ -hsx * | sort -rh | head -2 | tail -1

With sed, just add:

 | sed -n 2p

And no need to do that extra head.

Complete command:

du /etc/ -hsx * | sort -rh | sed -n 2p

If you want to stick to using head after sort, then add this tail:

 | tail +2

Complete command:

du /etc/ -hsx * | sort -rh | head -2 | tail +2

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .