I need to pass a list of sorted, quoted FLAC file names to SoX for concatenation but am having trouble getting sort to work the way I expect it to.

If I use:

find . -maxdepth 1 -type f -iname "*.flac" | sort

I get exactly what I expect:

./02-Both Sides Now.flac
./03-Solitary Man.flac
./04-Holly Holy.flac
./05-Cherry Cherry.flac
./06-Kentucky Woman.flac
./07-Sweet Caroline.flac
./08-Thank the Lord for the Nightime.flac
./09-And the Singer Sings His Song.flac
./10-Brother Loves Traveling Salvation Show.flac

However, I can't really use that for what I'm doing since I need a quoted list with no newlines. I know -printf can do that for me, but when I try:

find . -maxdepth 1 -type f -iname "*.FlAc" -printf "\"%p\" " | sort

I wind up with a list of file names that are quoted and separated by a single space (good!) but they aren't sorted (bad!). Or at least they aren't sorted the way I expect them to be:

"./08-Thank the Lord for the Nightime.flac" "./03-Solitary Man.flac" "./09-And the Singer Sings His Song.flac" "./05-Cherry Cherry.flac" "./06-Kentucky Woman.flac" "./10-Brother Loves Traveling Salvation Show.flac" "./07-Sweet Caroline.flac" "./02-Both Sides Now.flac" "./01-Lordy.flac" "./04-Holly Holy.flac"

Maybe even weirder, if I just for the sake of testing use the same code but add a newline:

find . -maxdepth 1 -type f -iname "*.FlAc" -printf "\"%p\" "\\n | sort

The sort works even if the output is back to not being what I need:

"./02-Both Sides Now.flac" 
"./03-Solitary Man.flac" 
"./04-Holly Holy.flac" 
"./05-Cherry Cherry.flac" 
"./06-Kentucky Woman.flac" 
"./07-Sweet Caroline.flac" 
"./08-Thank the Lord for the Nightime.flac" 
"./09-And the Singer Sings His Song.flac" 
"./10-Brother Loves Traveling Salvation Show.flac"

This is under Ubuntu 18.04.1

  • Do you have to use find here, for the recursion? Or are all the desired files in the same directory? (I ask, given the -maxdepth 1 and the sample output indicating the same directory) – Jeff Schaller Jan 20 at 1:48
  • 1
    I think what you're overlooking is that sort sorts lines (or, with GNU sort -z, null-delimited elements) - it should be no surprise that it doesn't sort filenames when they're all on a single line – steeldriver Jan 20 at 1:58
  • 2
    If you a) are using GNU sed and b) you really need to find your files recursively, you can use this: find . -iname '*.flac' -print0 | sort -z | xargs -0 sox ... instead of messing with quoting and unquoting. – mosvy Jan 20 at 2:00
  • @mosvy I was just experimenting with that idea; that seems like a good additional answer! – Jeff Schaller Jan 20 at 2:00
  • If you're trying to collect filenames to pass to SoX as command-line arguments, you do not want to put quotes around them. Quotes are parsed only when they're actually part of the command, not when they're in date (e.g. from a variable or command substitution). See here for an example. – Gordon Davisson Jan 20 at 4:28

If the files are all in the same directory, and you want to pass a list of sorted filenames to sox, then the bash shell could do that directly:

shopt -s nocaseglob
sox *.flac

The nocaseglob shell option allows the wildcard to pick up foo.FLAC, foo.Flac, foo.flaC, etc. The wildcard expands to an alphabetically sorted list, much like a bare sort would. It would, for example, put 9-file.flac after any filename that started with 8.

Thanks to @mosvy for a simplification of the above bash-ism into a wildcard that should work with any shell:

sox *.[Ff][Ll][Aa][Cc]

The brackets allow any combination of upper- and lower-case letters in the "flac" extension, in order to match what your find ... -iname "*.FlAc" was doing.

  • 2
    no need for nocaseglob; sox *.[fF][lL][aA][cC] will do just fine, in any shell. – mosvy Jan 20 at 1:57
  • Thank you everyone. sox *.[fF][lL][aA][cC] looks like it works while printf '%s\n' *.[Ff][Ll][Aa][Cc] looks like it gives me what I need to double-check that the order is correct. – atrocity Jan 20 at 5:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.