2011-08-19 94 views
41

在for循环中像这样的:文件名不带扩展名在bash for循环

for f in `ls *.avi`; do echo $f; ffmpeg -i $f $f.mp3; done 

$ F将是完整的文件名,包括扩展名。例如,对于song1.avi,命令的输出将是song1.avi.mp3。有没有办法只得到song1,没有for循环中的.avi?

我想有些方法可以使用awk或其他工具来实现,但我希望有更直接的方法。

感谢

+4

顺便说一句,你不想失去反引号的无用使用。正确和习惯的语法是'for * in * .avi;做......' – tripleee

+0

更不用说 - 如果你在文件名中有空格(尽管这是一种邪恶的做法),你实际上应该像'ls * avi |同时读f;做(...); done'。然后在每个地方引用'“$ f”'。只是说。 –

回答

60

使用bash参数扩展

${f%%.*} 

请注意,你需要贪婪的版本,因为有文件名多点。

从bash的手册:

$ {参数%字}

$ {参数%%字}

word被扩展,以产生一个模式,就像在文件名扩展。如果模式匹配参数扩展值的尾部分,则扩展结果是匹配模式最短的参数值('%'情况)或最长匹配模式('%%'情况)删除。如果参数是'@'或'',则将模式删除操作依次应用于每个位置参数,并且扩展是结果列表。如果参数是一个以'@'或''为下标的数组变量,则模式删除操作将依次应用于数组的每个成员,并且该扩展是结果列表。

+28

使用'$ {f%。*}' - 如果您使用'$ {f %%。*}'而$ f是“one.two.avi”,您将得到“one”而不是“one”。两个“ –

12

这应做到:

for i in *.m4a; do 
    ffmpeg -i $i ${i%%.*}.mp3 
done 
+2

对于一个已知的扩展(比如在'for'列表中),你可以使用'basename $ i .m4a'(反引号),但是一旦你记住'%。*'(百分之一,可以说更好),你不会再回头看。 –

+1

由于缺乏引号,这有点bug。使它成为'ffmpeg -i“$ i”“$ {i %%。*}。mp3”'将修复对带有空格的文件名的支持。 (顺便说一句,这些是http://shellcheck.net/可以捕获的问题)。 –