0

I have many folders in one directory, each containing 2 mp3 files. Hereby I can find the files:

first=$(find ./*/* -type f | sort | awk 'NR % 2 == 1')
second=$(find ./*/* -type f | sort | awk 'NR % 2 == 0')

I want to concatenate the first file with the second one in each folder:

ffmpeg -i "concat:$first|$second" -c copy "both_"$first

I have found this stackoverflow answer, but I don't know if and how I can use it for my purpose.

directory structure:

folder "files"
  |
  |--folder1
  |      |--001_001.mp3
  |      |--001_003.mp3
  |
  |--folder2
         |--001_004.mp3
         |--001_009.mp3
  ...

Any help would appreciated.

  • Can you show an example of the directory structure that you have? What determines which file should be the first and which should be tho second (just sorting on filename?) – Kusalananda Sep 14 '19 at 7:16
  • @Kusalananda – Yes, just sorting on filename, as shown above. The filenames have increasing numbers, on which I can sort them. – elli Sep 14 '19 at 13:07
4

I think it would be simpler and more robust to not rely on find in this instance. You have a well defined directory structure and there's really no reason to use find to traverse it since you know exactly where your files are.

Instead, use a shell loop:

for dirpath in files/*/; do
    set -- "$dirpath"/*.mp3
    ffmpeg -i "concat:$1|$2" -c copy "$dirpath/both_${1##*/}"
done

or alternatively,

for dirpath in files/*/; do
  (
    cd "$dirpath"
    set -- *.mp3
    ffmpeg -i "concat:$1|$2" -c copy "both_$1"
  )
done

This would loop over your folder1, folder2 etc. directories, with the pathname of each directory in $dirpath. For each directory pathname, the body of the loop would expand the *.mp3 globbing pattern in that directory and then use the first two matches of that pattern to run the ffmpeg command. No check is done to make sure that we actually get two matches of the pattern.

The difference between the two loops above is that the first loop does not change its directory to each of the $dirpath directories, and therefore $1 and $2 will contain the directory path of the directory. This is why I use "$dirpath/both_${1##*/}" to create the path to a file called both_something.mp3 in the directory (the directory path has to be stripped off from the start of $1 to insert the both_ substring).

The other loop uses cd to change directory into each directory in the loop. This way, the $1 and $2 strings would be filenames rather than pathnames with an initial directory path. Since the cd happens within a subshell (the (...)), the change of the working directory is only affecting the commands within the parentheses.

  • Both codes work perfectly. Thank you so much! – elli Sep 14 '19 at 7:54

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.