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

176,312

Solution 1

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

Solution 2

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("\0".join(sorted(sys.stdin.read().split("\0"))))' | xargs -r0 myCommand

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

Solution 3

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

Solution 4

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

Solution 5

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.
Share:
176,312
Industrial
Author by

Industrial

I just want to lie on the beach and eat hot dogs. That’s all I’ve ever wanted. Really.

Updated on September 18, 2022

Comments

  • Industrial
    Industrial almost 2 years

    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
    
  • Industrial
    Industrial over 12 years
    Well, that print0 appears to be space-separating the filenames which is what I need to pass to my command, unfortunately
  • Peter.O
    Peter.O over 12 years
    Good one (two?)... Interestingly, though, the two methods handle . differently... With sort it winds up at the end of the list... with python it sorts to the top. (maybe python sorts with LC_COLLATE=C)
  • Peter Mortensen
    Peter Mortensen almost 10 years
    What is the justification for using GNU Parallel? To speed it up?
  • Ole Tange
    Ole Tange almost 10 years
    That and you do not need to mess with \0 separated records.
  • Javier
    Javier almost 9 years
    There is also the -t \0 option for sort (which is a -z synonym)
  • syntaxerror
    syntaxerror over 8 years
    The problem with all these |sort solutions is that you cannot use -exec any longer. OK, although it is possible to rewrite your statement given to -exec so that it works with xargs, the question is, what about "mini-scripts"? (sh -c ...) I wouldn't call that trivial to transform a 'sh -c' mini-script with multiple commands so that it can work with xargs (if possible at all, that is)
  • Roger Pate
    Roger Pate almost 8 years
    @syntaxerror: What problem do you have using sh -c with xargs? printf %s\\n a b c d e | xargs -n3 sh -c 'printf %s, "$@"; printf \\n' x
  • uav
    uav about 4 years
    I don't understand that last statement. I create a file with a line break in the file name and execute your command: cd /tmp && touch $'a\nz' && ls && find -maxdepth 1 -print | sort | parallel echo. Total false output. I know GNU Parallel now, but that answer misses the original question, doesn't it?
  • uav
    uav about 4 years
    I know that it is bad practice to use crazy characters in file names - I am already including the blank space. I just see that parallel has a -0 parameter. Nice. No downvote. find -maxdepth 1 -print0 | sort -z | parallel -0 echo.
  • Ole Tange
    Ole Tange about 4 years
    @uav In my 25 years of sysadmin I have never seen a user making a file with \n. I have seen plenty of files with ' space and ". So unless you have evil users or a filesystem with error, I will reckon you will not meet a file with \n that was not made by a fellow sysadm.
  • bomben
    bomben over 3 years
    It does not seem to work with find . -name '*.dat' -type f -printf '%f\n' | sort -z | xargs -r0 > output.txt. Is my line wrong due to the printf?
  • ychaouche
    ychaouche about 3 years
    @Ben you're not using -print0 and are introducing newlines instead of NULLs.
  • BMWW
    BMWW almost 3 years
    or together with formating the output find . -printf "%y %p \n\0" | sort -z