1. Overview

The find command is part of GNU Utils and is used to search for files or directories in a directory hierarchy.

In this tutorial, we’ll explore find‘s default sorting order and look at several ways to organize the output.

2. The Default Sorting Order of find

The find command on Linux does not have a built-in sorting order. It traverses the file system and prints the results in the order in which it finds them.

However, we can pipe the find‘s output to another command to sort it, for example, the sort command.

3. Sorting the Output of find

Let’s sort the output of find using sort. We’re going to create a sample directory structure and then sort the output of the find command by filename, filename in natural order, directory, or directory in natural order.

3.1. Create a Directory Structure

First, let’s create a directory structure to play around with:

$ mkdir a b c
$ touch a/file1.txt a/file10.txt a/file11.txt
$ touch b/file5.txt b/file50.txt b/file51.txt
$ touch c/file3.txt c/file30.txt c/file31.txt
$ tree
.
├── a
│   ├── file10.txt
│   ├── file11.txt
│   └── file1.txt
├── b
│   ├── file50.txt
│   ├── file51.txt
│   └── file5.txt
└── c
    ├── file30.txt
    ├── file31.txt
    └── file3.txt

3 directories, 9 files

Next, let’s search and list all the txt files in those directories:

$ find . -type f -name '*.txt'
./a/file10.txt
./a/file1.txt
./a/file11.txt
./b/file50.txt
./b/file51.txt
./b/file5.txt
./c/file30.txt
./c/file3.txt
./c/file31.txt

As we can see above, the output order is somewhat random because the find command just traversed the file system and printed the results in the order in which it found them.

There are several different sorting orders that can be applied to the results, such as sorting by name, size, or modification time. We’ll focus only on sorting by filename or directory name.

3.2. Sort by Filename

Let’s sort the find command output by filename.

We can’t sort the output of find using sort directly because the output of the find command gives the full path of each file:

 find . -type f -name '*.txt' | sort
./a/file10.txt
./a/file11.txt
./a/file1.txt
./b/file50.txt
./b/file51.txt
./b/file5.txt
./c/file30.txt
./c/file31.txt
./c/file3.txt

If we sorted this data, the files would be sorted within each directory, but the directory names to the left of the filenames would have the most influence on the sort order.

However, we can use a workaround by adding a new column with just the filename. Then, we can sort the rows based on that column and cut it off before outputting the results.

Let’s start with adding a new column with just the filename:

$ find . -type f -name '*.txt' -printf '%f\t%p\n'
file10.txt   ./a/file10.txt
file1.txt    ./a/file1.txt
file11.txt   ./a/file11.txt
file50.txt   ./b/file50.txt
file51.txt   ./b/file51.txt
file5.txt    ./b/file5.txt
file30.txt   ./c/file30.txt
file3.txt    ./c/file3.txt
file31.txt   ./c/file31.txt

Next, we sort the new column using the command ‘sort -k1‘:

$ find . -type f -name '*.txt' -printf '%f\t%p\n' | sort -k1
file10.txt   ./a/file10.txt
file11.txt   ./a/file11.txt
file1.txt    ./a/file1.txt
file30.txt   ./c/file30.txt
file31.txt   ./c/file31.txt
file3.txt    ./c/file3.txt
file50.txt   ./b/file50.txt
file51.txt   ./b/file51.txt
file5.txt    ./b/file5.txt

And finally, we print the second column of the sorted output using the cut command (specifically, ‘cut -f2‘):

$ find . -type f -name '*.txt' -printf '%f\t%p\n' | sort -k1 | cut -f2
./a/file10.txt
./a/file11.txt
./a/file1.txt
./c/file30.txt
./c/file31.txt
./c/file3.txt
./b/file50.txt
./b/file51.txt
./b/file5.txt

As we can see from the above, the results are sorted in lexicographic order, which is also known as alphabetical, dictionary, or lexical order. For example, ‘file10.txt‘ appears before ‘file3.txt‘ because the ‘1‘ in the first string is smaller than ‘3‘ according to the sorting order. We may prefer that our numbers appear in numeric order.

3.3. Sort by Filename in Natural Order

In natural order, the sorting algorithm arranges strings lexically while taking into account the numerical value of any digits that appear within the string as a whole number rather than as individual characters.

For example, lexical sorting:

  • file11.txt
  • file2.txt

and natural sorting:

  • file2.txt
  • file11.txt

Unlike the default lexicographic sorting order, the natural sorting order is more human-friendly.

Let’s demonstrate the natural sorting order:

$ find . -type f -name '*.txt' -printf '%f\t%p\n' | sort -Vk1 | cut -f2
./a/file1.txt
./c/file3.txt
./b/file5.txt
./a/file10.txt
./a/file11.txt
./c/file30.txt
./c/file31.txt
./b/file50.txt
./b/file51.txt

As we can see above, after using the ‘-k1‘ option to sort the first column of the output, we applied the ‘-V‘ option to enable natural sorting order.

3.4. Sort by Directory

Since the find command gives the full path of the file, which is basically a string, we can just sort them directly without having to print two columns like in the previous subsection:

$ find . -type f -name '*.txt' | sort
./a/file10.txt
./a/file11.txt
./a/file1.txt
./b/file50.txt
./b/file51.txt
./b/file5.txt
./c/file30.txt
./c/file31.txt
./c/file3.txt

We sorted the output by directory name lexically, as shown above.

3.5. Sort by Directory in Natural Order

To sort by directory in natural order, we can pass the ‘-V‘ option:

$ find . -type f -name '*.txt' | sort -V
./a/file1.txt
./a/file10.txt
./a/file11.txt
./b/file5.txt
./b/file50.txt
./b/file51.txt
./c/file3.txt
./c/file30.txt
./c/file31.txt

As we can see above, the ‘-V’ option ordered the output by directory in natural order, including the files inside of each directory.

This makes it easier to locate specific files within each directory, especially when dealing with large or complex file systems.

4. Conclusion

In this tutorial, we learned that the find command doesn’t have a built-in sorting order. Therefore, we explored several different sorting orders using the sort command to organize the output in a way that best suits our needs.