36

I want to solve the problem 'list the top 10 most recent files in the current directory over 20MB'.

With ls I can do:

ls -Shal |head

to get top 10 largest files, and:

ls -halt |head

to get top 10 most recent files

With find I can do:

find . -size +20M

To list all files over 20MB in the current directory (and subdirectories, which I don't want).

Is there any way to list the top ten most recent files over a certain size, preferably using ls?

6 Answers 6

30

The 'current directory' option for find is -maxdepth 1. The whole commandline for your needs is:

find . -maxdepth 1 -type f -size +20M -print0 | xargs -0 ls -Shal | head

or

find . -maxdepth 1 -type f -size +20M -print0 | xargs -0 ls -halt | head
1
8

Note: This will work for GNU-find, but not every other find.

find . -maxdepth 1 -size +20M -printf "%T@ %f\n" | 
    sort -nr | head -n 20 | sed 's/[^ ]\+ //'

Starting like @Rajish, but using the printf command from find to specify the output format. There are 3 time-related formats, atime, ctime and mtime - %T is for mtime, %A and %C are for the other formats.

@ is to specify the timeformat in seconds since epoch. %f is for the filename, \n for a newline between 2 files.

Then sorting by number in reversed order gives the youngest files first, and we take 20 lines¹ with head.

In the end, sed is used, to throw away the time information.

¹) since head works line by line, a single file with more than 20 newlines in the name, which is a bit unusual, but not prohibited, can corrupt the output if it is belong the first 20 matches. If you happen to have such files, please try to get rid of them - well, to change their name. They will often be a problem for simple scripts.

3
  • 1
    If you use file's -ls command, the special characters will be printed as backslash-escaped characters: find . -maxdepth 1 -size +20M -printf "%T@ " -ls | sort -nr | head -n 20 | sed 's/[^ ]\+ //'. Additionally the format will look like ls -l, EoghanM also specified -l anyway.
    – manatwork
    Sep 13, 2011 at 15:39
  • printf only works for specific GNU distributions.
    – Brethlosze
    Nov 28, 2017 at 20:42
  • %T+ generates human readable timestamps like2018-11-06+13:37:54.4606466460 which are also sortable by sort (without -n), see: unix.stackexchange.com/questions/29899/… Apr 8, 2019 at 10:22
6

Zsh's glob qualifiers make this easy. The . qualifier selects only regular files, Lm+20 selects files that are at least 20MB plus one byte long; to include files that are exactly 20MB long, use L+20971519. Then om sorts by decreasing modification time, and [1,10] restricts the expansion to the first 10 matches. You still need the -t option to ls if you want to list the files by date; or you can pass the files to some other command (youngest first). To pass the files to another command with the oldest file first, use Om to sort by increasing modification time and [-10,-1] to extract the last 10 matches.

ls -ltr -- *(.Lm+20om[1,10])
echo *(.Lm+20Om[-10,-1])
2

I think this might be a better way to solve the problem...

find . -maxdepth 1 -type f -size +20M -exec ls -Shal {} \+ | head

To get rid of any errors while find tries to access files that you don't have permission to read you might want to add

find . -maxdepth 1 -type f -size +20M -exec ls -Shal {} \+ 2> /dev/null | head 
1

This will print only the specified 10 files, regardless of any embedded newline chars in file names. It uses file system inodes

cd "$1"
for i in $(find . -maxdepth 1 -type f -size +20M -printf "%T@\t%i\n" \ 
           | sort -nr | head | cut -f 2)
do
  ls -l "$(find . -inum $i)"
done
-1

Thanks for all the answers. What I've gone for is the following:

ls -halt | grep "M " |head

Although it forgoes the 20 Megabytes in favour of anything over a megabyte (and under a gigabyte), it's easy to remember and preserves the human readable element of the filesizes.

2
  • 4
    You should not attempt to parse the output of ls, it shows you a representation of files, nothing more. For simple file names, the output mostly happens to be equivalent to the file name, but you shouldn't rely on it.
    – Chris Down
    Sep 15, 2011 at 9:38
  • That's true I'm sure, but in terms of a human user (and output not being piped elsewhere), this one is easier to remember as it can be put together easier from known simple tools tldp.org/LDP/GNU-Linux-Tools-Summary/html/c1089.htm
    – EoghanM
    Nov 25, 2019 at 10:32

You must log in to answer this question.

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