2011-08-19 88 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/可以捕獲的問題)。 –