bash for循环中没有扩展名的文件名

Bog*_*lan 51 bash

在像这样的for循环中:

for f in `ls *.avi`; do echo $f; ffmpeg -i $f $f.mp3; done
Run Code Online (Sandbox Code Playgroud)

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

我想有办法使用awk或其他类似的工具,但我希望有更直接的东西.

谢谢

Mu *_*iao 73

使用bash参数扩展

${f%%.*}
Run Code Online (Sandbox Code Playgroud)

请注意,您需要贪婪版本,因为文件名中有多个点.

从bash手册:

$ {参数%字}

$ {参数%%词}

这个词被扩展为产生一个模式,就像文件名扩展一样.如果模式匹配参数展开值的尾部,那么展开的结果是具有最短匹配模式('%'大小写)或最长匹配模式('%%'大小写)的参数值删除.如果参数为'@'或' ',则模式删除操作依次应用于每个位置参数,并且扩展是结果列表.如果参数是使用'@'或' ' 下标的数组变量,则模式删除操作依次应用于数组的每个成员,并且扩展是结果列表.

  • 使用`$ {f%.*}` - 如果你使用`$ {f %%.*}`而$ f是"one.two.avi",你将获得"one"而不是"one.two" " (32认同)

小智 15

这应该这样做:

for i in *.m4a; do
  ffmpeg -i $i ${i%%.*}.mp3
done
Run Code Online (Sandbox Code Playgroud)

  • 对于一个已知的扩展名(比如在`for`列表中),你可以使用`basename $ i .m4a`(在反引号中),但是一旦你记住`%.*`(百分之一,可以说,更好),你不会再回头看了. (2认同)
  • 由于缺少报价,这有点儿麻烦.使它成为`ffmpeg -i"$ i""$ {i %%.*}.mp3"`将修复对带空格的文件名的支持.(顺便说一句,这些是http://shellcheck.net/可以捕获的问题). (2认同)