我创建了一个Shell脚本,将所有wave文件转换为mp3文件。我使用Ubuntu 18.04,使用apt安装了FFmpeg,然后在bash中运行脚本。
我的脚本:
#!/bin/bash
ls *.wav | while read file
do
echo $file
ffmpeg -i "$file" -codec:a libmp3lame -b:a 192k "${file%.*}.mp3"
done
目标文件如下:(包括空格字符。实际文件名较长,但是我简化了文件名。在这种情况下,也会出现问题)
% ls *.wav
'01 A.wav' '02 A.wav' '03 A.wav'
问题在于,有时循环中的$ file是空白或文件名的一部分很奇怪('echo $ file'表明了这一点),而ffmpeg则说'[[破碎的文件名]:没有这样的文件或目录”。我确认了以下内容。
因此,仅当我使用'ls'和'ffmpeg'的组合时,$ file才损坏。这是怎么回事?还是我误会了什么?
答案 0 :(得分:2)
您不应使用ls
来传送文件列表,因为这种方法不适用于某些情况,例如文件名带有空格。
最易读的方式是使用 globbing :
for file in *.wav
do
echo "$file"
ffmpeg -i "$file" -codec:a libmp3lame -b:a 192k "${file%.*}.mp3"
done
查找在这里也做得很好,但是最终您将得到一些不太易于维护的代码:
find -name *.wav -exec ffmpeg -i {} -codec:a libmp3lame -b:a 192k {}.mp3 \;
find
示例将为您提供以.wav.mp3
结尾的文件名而不是.mp3
,如果要避免这种情况,则必须从find调用shell,从而允许您使用basename
或执行类似${file.*}
的操作(您必须首先在该shell中将find的{}
分配给类似file
的变量:
find -name "*.wav" -exec sh -c "file=\"{}\" ; ffmpeg -i \"\$file\" -codec:a libmp3lame -b:a 192k \${file%.*}.mp3" \;