Sorting the output of "find -print0" by piping to the "sort" command

I need to be able to alphabetically sort the output of find before piping it to a command. Entering | sort | between didn’t work, so what could I do?

find folder1 folder2 -name "*.txt" -print0 | xargs -0 myCommand
Asked By: Industrial

||

I think you need the -n flag for sort#

According to man sort:

-n, --numeric-sort
    compare according to string numerical value

edit

The print0 may have something to do with this, I just tested this. Take the print0 out, you can null terminate the string in sort using the -z flag

Answered By: whoami

Use find as usual and delimit your lines with NUL. GNU sort can handle these with the -z switch:

find . -print0 | sort -z | xargs -r0 yourcommand
Answered By: Oli

Some versions of sort have a -z option, which allows for null-terminated records.

find folder1 folder2 -name "*.txt" -print0 | sort -z | xargs -r0 myCommand

Additionally, you could also write a high-level script to do it:

find folder1 folder2 -name "*.txt" -print0 | python -c 'import sys; sys.stdout.write("".join(sorted(sys.stdin.read().split(""))))' | xargs -r0 myCommand

Add the -r option to xargs to make sure that myCommand is called with an argument.

Answered By: Arcege

If you have GNU Parallel http://www.gnu.org/software/parallel/ installed you can do this:

find folder1 folder2 -name "*.txt" -print | 
  sort |
  parallel myCommand

You can install GNU Parallel simply by:

wget http://git.savannah.gnu.org/cgit/parallel.git/plain/src/parallel
chmod 755 parallel
cp parallel sem

Watch the intro videos for GNU Parallel to learn more:
https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

Answered By: Ole Tange

Some implementation of find supports ordered traversal directly via the -s parameter:

$ find -s . -name '*.json'

From the FreeBSD find man page:

-s       Cause find to traverse the file hierarchies in lexicographical
         order, i.e., alphabetical order within each directory.  Note:
         `find -s' and `find | sort' may give different results.
Answered By: raychi

Some solutions here don’t work correctly because the sort command takes the full "path" string to sorting instead of the filename string.

This is a quite complicated but working example of natural sorting results of the "find" command:

find every_minute -type f -name "*.sh" -printf '%ft%pn' | sort -V -k1 | cut -d$'t' -f2 | tr 'n' '' | xargs -r0 -I {} echo 'Found: "{}"'

Result:

Found: "every_minute/api/1_build_synonyms.sh"
Found: "every_minute/search_module/2_rotate_index.sh"
Found: "every_minute/api/3_check_synonyms.sh"
Found: "every_minute/api/4_run_schedule.sh"
Found: "every_minute/search_module/10_test.sh"

Example of an invalid find every_minute -type f -name "*.sh" | sort -z | xargs -r0 echo command result:

every_minute/api/1_build_synonyms.sh
every_minute/api/3_check_synonyms.sh
every_minute/api/4_run_schedule.sh
every_minute/search_module/10_test.sh
every_minute/search_module/2_rotate_index.sh

Based on this answer.

Answered By: James Bond
Categories: Answers Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.