0

All,
I want to list the top 5 image files (png,jpg) in a given folder.What's the best approach? I'm using the following currently but it doesn't give the right output:

find . \( -iname \*.png -o -iname \*.jpg \)  -exec ls -lrhS {} \; | sort -n | head -5 | awk '{print $9, "=>",$5}'

When I don't pipe to head command, I see that the output isn't sorted correctly. How can I achieve this

1
  • Since you run ls individually per file, its sorting function won't work. It will "sort" every file individually, so to speak. Apr 6, 2012 at 9:35

5 Answers 5

1

If by "top 5" you mean by size, then you need to tell sort which column to sort by; the default will go through all the columns in order, meaning it's going to sort initially by the number of links. Additionally, without some kind of extension the "human readable" size is not going to sort at all sanely except in GNU sort; portable sort -n does not know about suffixes like B, K, etc. Note also that you lose the sort information you asked ls for because it's being run on individual files under control of find. And then your sort sorts from lowest to highest, so even fixing that you get the five smallest images from head. (And is the || before awk a typo? You're saying to run awk only if the find pipeline fails.)

Combining all of this and optimizing by using xargs to batch things up and combining the head into the awk, what you want is to make sure you have GNU sort, then use

find . \( -iname \*.png -o -iname \*.jpg \) -print0 | xargs -0 ls -lh | sort -k5gr,5 | awk 'NR <= 5 {print $9, "=>", $5}'
4
  • the || before awk is indeed a typo. Also how do I find if I have the GNU sort? I'm on MAC OSX
    – smokinguns
    Apr 6, 2012 at 5:25
  • sort --version will return useful information for GNU sort or an error for traditional Unix sort, or possibly information about some other implementation — but OS X uses the version of GNU sort that the version of FreeBSD it last synced with uses (I believe that's FreeBSD 8.0 for Lion; sort is GNU sort 5.93.)
    – geekosaur
    Apr 6, 2012 at 5:54
  • geekosaur : The command didnt give me the correct output. What does "sort -k5gr,5" do exactly?
    – smokinguns
    Apr 6, 2012 at 6:07
  • It means general numeric sort (which in GNU sort is supposed to support things like 1.1K) reversed, from column 5 to column 5 (that is, just the one column). (It is 1-based, unlike the usual 0-based computer thing.) That said, I just tried it here and it looks like while GNU sort claims to handle the size suffixes on numeric columns, it actually doesn't; you will have to give up on the -h option to ls, and maybe change the awk script to do it instead.
    – geekosaur
    Apr 6, 2012 at 6:16
1
find . \( -iname "*.png" -o -iname "*.jpg" \) -printf "%k\t%p\n" | sort -rn | head -5
  1. Uses find according to your requirements in the current directory (I assume you mean "current directory AND subdirectories, otherwise add -maxdepth 1).
  2. Prints size (in 1K blocks), followed by tab, followed by filename.
  3. Sorts numerically reversed.
  4. Picks out the first five lines.

et voilà!

(Possible caveat is file names containing newlines, but in practice I have never seen these. Requires some simple modification to account for that as well)

2
  • I get an error : find: -printf: unknown option. Looks like I will have to install findutils
    – smokinguns
    Apr 6, 2012 at 15:47
  • @smokinguns Exactly. Are you on OS X or a BSD variant? You need GNU find for that, for example through Homebrew.
    – slhck
    Apr 6, 2012 at 15:59
1

Thanks to all pointing me in the right direction. I think I got it to work using:

find . \( -iname \*.png -o -iname \*.jpg \) -print0 | xargs -0 ls -l | sort -k5 -r | head -5

I will process this output to get the output in desired format(i.e. with suffixes like B, K)

0

Do you mean "top" as in largest by size? The S in your ls command already sorts by size, but r reverses the order, sorting smallest to the top. Perhaps you want to try -exec ls -lhS {} \; | head -5 (omit the separate sort).

2
  • Sorting the output of ls (with l -S) is pointless, becaue ls executes on only a single file at a time; courtesy of {} \;
    – Peter.O
    Apr 6, 2012 at 7:25
  • @Peter.O -- You're absolutely right, I missed that. I suppose one could omit the find completely using something like ls -lhS *.png *.PNG *.jpg *.JPG | head -5 | awk '{print $9, "=>",$5}'. Depends on what suits his needs. Apr 6, 2012 at 15:04
0

Sort of very straightforward:

find . -ls | sort -nk7 | tail -5
2
  • 1
    This doesn't restrict to image files, and gives a lot of for the task unnecessary information. Apr 6, 2012 at 9:31
  • Asker knows how to list files in good format. I just illustrate how to get 10 top records based on numeric field in 7th position. I assume asker's creativity is enough to correct my deliberate omissions.
    – ZaB
    Apr 9, 2012 at 13:28

You must log in to answer this question.

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