sorting output of find before running the command in -exec
Asked Answered
U

1

5

I have a series of directories containing multiple mp3 files with filenames 001.mp3, 002.mp3, ..., 030.mp3.

What I want to do is to put them all together in order into a single mp3 file and add some meta data to that.

Here's what I have at the moment (removed some variable definitions, for clarity):

#!/bin/bash
for d in */; do
    cd $d
    find . -iname '*.mp3' -exec lame --decode '{}' - ';' | lame --tt "$title_prefix$name" --ty "${name:5}" --ta "$artist" --tl "$album" -b 64 - $final_path"${d%/}".mp3
    cd ..
done

Sometimes this works and I get a single file with all the "tracks" in the correct order.

However, more often than not I get a single file with all the "tracks" in reverse order, which really isn't good.

What I can't understand is why the order varies between different runs of the script as all the directories contain the same set of filenames. I've poured over the man page and can't find a sort option for find.

I could run find . -iname '*.mp3' | sort -n >> temp.txt to put the files in a temporary file and then try and loop through that, but I can't get that to work with lame.

Is there any way I can put a sort in before find runs the exec? I can find plenty of examples here and elsewhere of doing this with -exec ls but not where one needs to execute something more complicated with exec.

Upstream answered 22/7, 2016 at 12:39 Comment(3)
Pushing the boundaries of my own bash abilities here but could I do something like find . -iname '*.mp3' | sort -n | xargs <something_here>? If so how would I re-arrange the lame command to take an input?Upstream
temp.txt include full path or only series of file names ?Effortful
I'd rather not use a temporary file at all if possible. But it could presumably be constructed to contain any type of filename.Upstream
I
8
find . -iname '*.mp3' -print0 | sort -zn | xargs -0 -I '{}' lame --decode '{}' - | lame --tt "$title_prefix$name" --ty "${name:5}" --ta "$artist" --tl "$album" -b 64 - $final_path"${d%/}".mp3

Untested but might be worth a try.

Normally xargs appends the arguments to the end of the command you give it. The -I option tells it to replace the given string instead ({} in this case).


Edit: I've added -print0, -z, -0 to make sure the pipeline still works even if your filenames contain newlines.

Ingold answered 22/7, 2016 at 13:44 Comment(2)
change sort -n to sort -zn because sort by default returns newline-separated recordsQuiz
i can't suggest edit -- at least 6 symbols should be added ))Quiz

© 2022 - 2024 — McMap. All rights reserved.