我正在尝试使用 find 和 FFmpeg 将所有 wav 和 mp3 文件递归地转换为 ogg 文件。我制作了以下 bash 脚本来执行此操作:
#!/usr/bin/env bash
# Converts samples to ogg
find samples \( -iname '*.wav' -o -iname '*.mp3' \) -execdir ffmpeg -i "$(basename "{}")" -qscale:a 6 "${$(basename "{}")%.*}.ogg" \;
然而,这会出错:
${$(basename "{}")%.*}.ogg: bad substitution
我需要如何格式化最后一个替换以使其返回后缀为 的文件的基本名称.ogg
,为什么这不起作用?
答案1
您似乎假设--execdir
调用(Bash)shell,然后调用 ffmpeg。事实并非如此:
-exec command ;
Execute command; true if 0 status is returned. All following
arguments to find are taken to be arguments to the command until
an argument consisting of `;' is encountered. The string `{}'
is replaced by the current file name being processed everywhere
it occurs in the arguments to the command, not just in arguments
where it is alone, as in some versions of find.
ffmpeg
被调用,find
并且 it ( ffmpeg
) 不知道如何处理您的特殊语法。
我只会制作一个小型 bash 脚本,它可以仅根据输入文件名处理一次转换,并将其用作-execdir
.
答案2
我最近写了一个例子将 shell 单行代码填充到find
命令中,这是另一个用例。
代替:
find samples \( -iname '*.wav' -o -iname '*.mp3' \) -execdir ffmpeg -i "$(basename "{}")" -qscale:a 6 "${$(basename "{}")%.*}.ogg" \;
尝试:
find samples \( -iname '*.wav' -o -iname '*.mp3' \) -exec sh -c 'ffmpeg -i "$1" -qscale:a 6 "${1%.*}.ogg"' find-sh {} \;
请注意,这find-sh
是任意文本;在它所在的位置,它被设置为 shell 的$0
.这并不重要,但它用于错误报告,因此最好在那里有一些描述性的内容。我认为find-sh
这是一个很好的名字。