循环遍历文件夹并使用 ffmpeg 连接 mp3 文件

循环遍历文件夹并使用 ffmpeg 连接 mp3 文件

我在一个目录中有很多文件夹,每个文件夹包含 2 个 mp3 文件。据此我可以找到这些文件:

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

我想将每个文件夹中的第一个文件与第二个文件连接起来:

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

我已经发现这个 stackoverflow 答案,但我不知道是否以及如何将它用于我的目的。

目录结构:

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

任何帮助将不胜感激。

答案1

find我认为在这种情况下不依赖会更简单、更稳健。您有一个定义良好的目录结构,并且实际上没有理由使用find它来遍历它,因为您确切地知道文件在哪里。

相反,使用 shell 循环:

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

或者,

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

这将循环遍历您的folder1folder2目录,其中每个目录的路径名都是$dirpath.对于每个目录路径名,循环体将扩展*.mp3该目录中的通配模式,然后使用该模式的前两个匹配来运行命令ffmpeg。没有进行任何检查来确保我们实际上获得了该模式的两个匹配项。

上面两个循环之间的区别在于,第一个循环不会将其目录更改为每个$dirpath目录,因此$1$2将包含该目录的目录路径。这就是为什么我用来"$dirpath/both_${1##*/}"创建目录中调用的文件的路径both_something.mp3(必须从开头删除目录路径$1才能插入both_子字符串)。

另一个循环用于cd将目录更改为循环中的每个目录。这样,$1$2字符串将是文件名而不是带有初始目录路径的路径名。由于cd发生在子 shell (the (...)) 内,工作目录的更改仅影响括号内的命令。

相关内容