我有一個充滿.bak文件和一些其他文件的文件夾。我需要刪除該文件夾中所有.bak文件的擴展名。如何創建一個接受文件夾名稱的命令,然後刪除該文件夾中所有.bak文件的擴展名?如何刪除文件的擴展名?
謝謝。
我有一個充滿.bak文件和一些其他文件的文件夾。我需要刪除該文件夾中所有.bak文件的擴展名。如何創建一個接受文件夾名稱的命令,然後刪除該文件夾中所有.bak文件的擴展名?如何刪除文件的擴展名?
謝謝。
要從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是替代解決方案。
有幾種方法可以刪除文件後綴:
在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
+1用於解釋,特別是'find.out'技術。在對文件系統做一些可能很醜陋的事情之前,這是一個非常好的方法來進行理智檢查。 –
rename .bak '' *.bak
(rename
是在util-linux
包)
您可以隨時使用find命令獲取所有子目錄
for FILENAME in `find . -name "*.bak"`; do mv --force "$FILENAME" "${FILENAME%.bak}"; done
如果文件名中有空格,該怎麼辦? –
謝謝。這很好。我可以讓這個命令爲任何目錄執行任務嗎?我不想一直光盤進入目錄。 – bashboy
btw,完成的含義是什麼? – bashboy