2013-07-24 271 views
4

我有一個充滿.bak文件和一些其他文件的文件夾。我需要刪除該文件夾中所有.bak文件的擴展名。如何創建一個接受文件夾名稱的命令,然後刪除該文件夾中所有.bak文件的擴展名?如何刪除文件的擴展名?

謝謝。

回答

8

要從BASH可變的末端除去一個字符串,可使用${var%ending}語法。這是a number of string manipulations available to you in BASH之一。

使用這樣的:

# Run in the same directory as the files 
for FILENAME in *.bak; do mv "$FILENAME" "${FILENAME%.bak}"; done 

這很好地工作作爲一個內膽,但你也可以把它包裝成一個腳本在任意目錄下工作:

# If we're passed a parameter, cd into that directory. Otherwise, do nothing. 
if [ -n "$1" ]; then 
    cd "$1" 
fi 
for FILENAME in *.bak; do mv "$FILENAME" "${FILENAME%.bak}"; done 

注意雖然引用變量幾乎總是一個好習慣,但如果任何文件名可能包含空格,則for FILENAME in *.bak仍然很危險。閱讀David W.的答案是更強大的解決方案,而this document是替代解決方案。

+0

如果文件名中有空格,該怎麼辦? –

+0

謝謝。這很好。我可以讓這個命令爲任何目錄執行任務嗎?我不想一直光盤進入目錄。 – bashboy

+0

btw,完成的含義是什麼? – bashboy

1

警告:沒有錯誤檢查:

#!/bin/bash 
cd "$1" 
for i in *.bak ; do mv -f "$i" "${i%%.bak}" ; done 
+0

你的腳本沒有工作,也掛着我的目錄結構。 – bashboy

+0

@bashboy:您的文件名中可能有空格?我修改了腳本以嘗試解釋它。 – jxh

6

有幾種方法可以刪除文件後綴:

在bash和Kornshell,您可以使用環境變量過濾。在BASH manpage中搜索${parameter%word}以獲取完整信息。基本上,#左側過濾器%右側過濾器。您可以記住這一點,因爲#位於%的左側。

如果您使用的是雙濾光片(即##%%,你想上最重要的比賽進行篩選。如果你有一個單一的過濾器(即#%,你想上最小的匹配過濾器。

匹配什麼是過濾出來,你得到的字符串的其餘部分:

file="this/is/my/file/name.txt" 
echo ${file#*/} #Matches is "this/` and will print out "is/my/file/name.txt" 
echo ${file##*/} #Matches "this/is/my/file/" and will print out "name.txt" 
echo ${file%/*} #Matches "/name.txt" and will print out "/this/is/my/file" 
echo ${file%%/*} #Matches "/is/my/file/name.txt" and will print out "this" 

請注意這是一個水珠比賽,而不是一個正則表達式匹配!如果你想牛逼Ø刪除文件後綴:

file_sans_ext=${file%.*} 

.*將匹配期間和之後的所有字符。由於它是單個%,因此它將與字符串右側的最小glob匹配。如果過濾器無法匹配任何內容,則與原始字符串相同。

您可以驗證文件後綴像這樣的東西:

if [ "${file}" != "${file%.bak}" ] 
then 
    echo "$file is a type '.bak' file" 
else 
    echo "$file is not a type '.bak' file" 
fi 

或者你可以這樣做:

file_suffix=$(file##*.} 
echo "My file is a file '.$file_suffix'" 

注意,這將刪除文件擴展名的時期。

下一步,我們將循環:

find . -name "*.bak" -print0 | while read -d $'\0' file 
do 
    echo "mv '$file' '${file%.bak}'" 
done | tee find.out 

find命令查找指定的文件。 -print0用NUL符號分隔文件的名稱 - 這是文件名中不允許的幾個字符之一。 -d $ \ means that your input separators are NUL symbols. See how nicely the find -print0 and讀-d $'\ 0'`在一起?

你應該幾乎從不使用for file in $(*.bak)方法。如果文件名稱中有空格,這將失敗。

請注意,該命令實際上並不移動任何文件。相反,它會生成一個帶有所有文件重命名列表的find.out文件。當你執行大量文件的命令時,你應該總是這樣做,以確保一切正常。

一旦你已經確定,在find.out所有的命令都是正確的,你可以像一個shell腳本運行:

$ bash find.out 
+0

+1用於解釋,特別是'find.out'技術。在對文件系統做一些可能很醜陋的事情之前,這是一個非常好的方法來進行理智檢查。 –

1

rename .bak '' *.bak

rename是在util-linux包)

0

您可以隨時使用find命令獲取所有子目錄

for FILENAME in `find . -name "*.bak"`; do mv --force "$FILENAME" "${FILENAME%.bak}"; done