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:
and natural sorting:
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.
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.