51

what is the default sorting order for entries returned by the linux find command?

For example, if I issue

find . -type f -name '*mp3' 

and the output consists of multiple files across multiple sub-folders, what is the default order in which directories are listed? At the same time, what is the sorting order in which files within an individual directory are listed?

Sometimes it returns:

./B/01.mp3
./A/01.mp3
./A/04.mp3
./A/02.mp3

See how first the contents of directory B is listed, then that of directory A. At the same time within directory A, files are listed in a funny order.

Nasko
  • 513
  • 1
  • 4
  • 4
  • From experience it seems to be consistent per install, ie. if you have the same set of files on two machines it will always return one order on one machine, and a completely different one on the other. I have wondered why before, +1 – James L Sep 16 '10 at 13:34
  • 2
    I have an FM transmitter in my car and it always plays songs from my flash card in strange order. I never figured it, but I recognized it was exactly the same order in which the above command returned its output – Nasko Sep 16 '10 at 14:10
  • 1
    BTW: BSD find has `-s` parameter to alphabetically sort output. – lapo Dec 02 '15 at 20:08

3 Answers3

34

find will be traversing the directory tree in the order items are stored within the directory entries. This will (mostly) be consistent from run to run, on the same machine and will essentially be "file/directory creation order" if there have been no deletes.

However, some file systems will re-order directory entries as part of compaction operations or when the size of the entry needs to be expanded, so there's always a small chance the "raw" order will change over time. If you want a consistent order, feed the output through an extra sorting stage.

Vatine
  • 5,390
  • 23
  • 24
  • Thanks for your detailed answer! So, if my FM transmitter (see my prev. comment) plays tracks in the order the find command would list them, I'm not able to control in what order I'd like them to be played. – Nasko Sep 17 '10 at 08:33
  • Well, the flash card probably uses a FAT file system and if I remember correctly, manipulating the order of FAT entries is pretty easy with a file system debugger. It may, possibly, be worth copying the songs from the current flash onto a new flash, in the order you want them played, that may be easier. – Vatine Sep 17 '10 at 10:39
  • One of the useful applications of such consistency is a progress estimation of slow `find /path/ -exec ...` with running much faster `find /path/` to get sorted list of files first. – Andrey Dec 14 '16 at 21:42
13

You shouldn't rely on a particular output order from find and instead should use sort and other means to specifically control the order.

Dennis Williamson
  • 60,515
  • 14
  • 113
  • 148
11

I have been working in UNIX/Linux since 1984/1991 respectively and the first command I was taught was find. Linux/GNU has put pretty much everything you need into the current find command so play around with it.

Here are some helpful tips for sorting find output. The -printf option gives you lots of options to enable more complex sorting and file info presentation. It is the best for problems like this. Play with it to see what will work for you. Using -printf you can customize and delimit the results the way you want. This helps quite a bit when you need to post process the results. I hope this helps someone.

  1. If you use -ls and want to sort by file name the 11th field is the file name so you can do the following. The sort -k option can take multiple fields to sort on as well.

    find /path -ls | sort -k11

  2. If you want finer grain control i.e.sort by date/time in ascending or descending order use the -printf "" option. See the manual for more detail, but the following is an example that will print with fractional seconds so it is very accurate.

EXAMPLE DATE/TIME: 2016-09-17+12:09:57.9013929800

find /path -printf "%T+ %p\n" | sort -n # Ascending

find /path -printf "%T+ %p\n" | sort -nr # Descending

Another way to do this without characters in the date/time string is.

EXAMPLE DATE/TIME: 20160917120013.8101685040

find /path -printf "%AY%Am%Ad%AH%AM%AS %p\n" | sort -n