是否有一个 zsh 脚本可以将一种音乐格式的目录文件转换为 Ogg opus 格式。这文件名中包含空格。
例如,一个目录包含10个扩展名为*.wma的文件
文件转换为*.wav
格式使用ffmpeg -i filename.wma filename.wav
文件*.wav
被转换为作品使用opusenc --bitrate 160 filename.wav filename.opus
更新:ffmpeg -i filename.wma -c:a libopus -b:a 128k filename.opus
用一个命令转换文件
部分工作的脚本将处理当前目录中从 .wma 到 .wav 的文件名,即使带有空格。但是,.wav
添加了扩展名而不是替换 *.wma 文件扩展名
该脚本被添加到一个名为的文件中convert
,并且该文件变得可执行
IFS=$'\n'
for x in *.wma ; do
echo $x
ffmpeg -i "$x" $x.wav
done
尝试使用Zsh 修饰符将文件扩展名替换为:(${x:e}".wav
在 ilkkachu 的建议后我也尝试过${x:r}".wav
)
IFS=$'\n'
for x in *.wma ; do
ffmpeg -i "$x" "${x:e}".wav
done
从名为的文件调用此文件convert
,将返回以下错误
./convert: 3: Bad substitution
同样的错误发生在
IFS=$'\n'
for x in *.wma ; do
ffmpeg -i "$x" "${x:r}".wav
done
我认为语法不太好写,或者当文件名有空格时修饰符不起作用。或者关于 zsh 我还有很多东西需要学习:)
是否有正确的方法来替换 Zsh 中的文件扩展名(当文件名包含空格时)
谢谢。
答案1
虽然您的问题是您将脚本解释为 ,sh
而不是zsh
, in zsh
,但您可以在此处使用zmv
:
#! /bin/zsh -
autoload zmv
zmv -P ffmpeg -o -i './(*).wma' './$1.wav'
zmv
通常会进行批量重命名,但也可以进行批量复制/链接或批量任何操作(如果给出执行该操作的命令名称)任何事物。
您可以从它在执行任何操作之前执行的少数保护措施中受益(检查目标文件是否不存在或两个源文件是否映射到同一目标)。
另请注意./
前缀,以避免以 开头的文件名出现问题-
,或者通常可以解决ffmpeg
.
在任何情况下,IFS=$'\n'
您的代码中的 都没有任何作用,因为您没有使用 IFS 分词(仅在命令替换和$=param
zsh 中完成),也没有使用诸如"$array[*]"
将数组元素与 的第一个元素连接之类的东西$IFS
,无论如何zsh
,您//宁愿使用s[sep]
参数扩展标志来分割或加入而不是全局更改。另请注意,换行符与文件名中的任何字符一样有效。f
0
j[sep]
$IFS
答案2
要使用 Zsh 修饰符(和其他 zsh 特定语法),添加到文件的脚本应首先将其定义为 zsh 脚本
#!/usr/bin/zsh
which zsh
(可选)如果不确定您的操作系统使用此位置,请首先检查 zsh 的位置
添加此行还可以在编辑器中打开文件时添加特定的 zsh 语法突出显示
shell 变量 IFS(内部字段分隔符)确定在分割字符串序列(例如目录列表)时如何识别单词边界。
在 zsh 中将IFS 设置为$'\n'
允许使用包含空格的文件名
IFS=$'\n'
使用for
循环将迭代当前目录中的所有文件,使用通配符 -*.wma
对于当前目录中的该文件扩展名或**/*.wma
当前目录和子目录
#!/usr/bin/zsh
IFS=$'\n'
for x in *.wma ; do
ffmpeg -i "$x" "${x:r}".wav
done
ffmpeg 可以使用libopus
音频编解码器转换为 opus 文件,因此不需要转换为 opusenc 工具支持的格式。
ffmpeg -i original-file.wma -b:a 128k -c:a libopus ouptut-file.opus
其中-b:a
是音频比特率,-c:a
是音频编解码器
将所有这些放在一起,最终的脚本是:
#!/usr/bin/zsh
IFS=$'\n'
for x in *.wma ; do
ffmpeg -i "$x" -b:a 128k -c:a libopus "${x:r}".opus
done