所以我刪除文件名中的特殊字符並用空格替換。除了其中包含單反斜槓的文件外,我已經開始工作了。 注意這些文件在Finder中創建了OS X刪除反斜槓與tr
old_name="testing\this\folder"
new_name=$(echo $old_name | tr '<>:\\#%|?*' ' ');
這將導致NEW_NAME被「測試hisolder」 如何我只是刪除了反斜槓,而不是前面的字符?
所以我刪除文件名中的特殊字符並用空格替換。除了其中包含單反斜槓的文件外,我已經開始工作了。 注意這些文件在Finder中創建了OS X刪除反斜槓與tr
old_name="testing\this\folder"
new_name=$(echo $old_name | tr '<>:\\#%|?*' ' ');
這將導致NEW_NAME被「測試hisolder」 如何我只是刪除了反斜槓,而不是前面的字符?
這將導致NEW_NAME被 「測試hisolder」
這個字符串看起來像echo -e "testing\this\folder"
的結果,因爲\t
和\f
實際上取代用製表符和換頁控制字符。
也許你有一個別名像alias echo='echo -e'
,或者可能的echo
在外殼的版本執行解釋反斜槓:
POSIX不需要任何選項的支持,並且說的 行爲如果任何STRING包含 反斜槓或第一個參數爲「-n」,則'echo'是實現定義的。如果便攜式程序需要省略尾部換行符或輸出控制字符或反斜槓,則可以使用'printf'命令使用 。
(從信息頁)
所以,你應該在新的軟件使用printf
,而不是echo
。特別是,echo $old_name
應替換爲printf %s "$old_name"
。
例如this discussion有一個很好的解釋。
無需printf
正如@ mklement0建議,您可以通過Bash here string的手段避免管道:
tr '<>:\\#%|?*' ' ' <<<"$old_name"
使用bash,你可以使用參數擴展:
$ old_name="testing\this\folder"
$ new_name=${old_name//[<>:\\#%|?*]/ }
$ echo $new_name
testing this folder
有關詳細信息,請參閱猛砸手冊上shell parameter expansion。
我認爲你的測試用例丟失了\
的正確轉義,所以你並不真正測試包含在字符串中的反斜槓的情況。
這爲我工作:
old_name='testing\\this\\folder'
new_name=$(echo $old_name | tr '<>:\\#%|?*' ' ');
echo $new_name
# testing this folder
在Bash(這是如何標記問題)中使用默認選項,使用它的'echo'內建,這將保留_both_反斜槓,並且結果字符串在單詞之間會有_2_空格。 (相反,OP的代碼應該按原樣工作。)除此之外,「$ old_name」應該用雙引號。你的轉義只能在打開(隱式或顯式)選項'xpg_echo'的情況下才能起作用,但更好的解決方案是使用'printf'或一個here-string。 – mklement0
Ruslan's excellent answer解釋了爲什麼你的命令可能不會爲你工作,並提供強大的便攜式解決方案。
TL;博士:
sh
而非bash
(即使在MacOS sh
這是Bash的化身)跑了你的代碼,或者你有shell選項xpg_echo
明確地打開。printf
而不是echo
。在bash,使用默認選項,並使用echo
內置,命令將正常運行,是(除了你應該用雙引號$old_name
穩健性),因爲echo
(默認設置)不在其操作數中擴展轉義序列,如\t
。
然而,bash的echo
可以進行擴大控制字符轉義序列:
shopt -s xpg_echo
sh
或與--posix
選項( ,以及其他選項和行爲變化,激活xpg_echo
)因此,您的s例如,ymptom可能是由腳本以腳本行#!/bin/sh
運行代碼引起的。
但是,如果你的目標sh
,即,如果你正在寫一個便攜式腳本,然後echo
應該完全避免的原因恰恰是它的行爲跨越炮彈和平臺的不同 - 見魯斯蘭的printf
解決方案。
順便說一句:或許是一個更強大的方式來你tr
命令是白名單方法:僅指出明確允許在結果中的字符,並排除其他與-C
選項:
old_name='testing\this\folder'
new_name=$(printf '%s' "$old_name" | tr -C '[:alnum:]_-' ' ')
這樣,任何不是字母,數字,_
或-
的字符都將替換爲空格。
感謝您的詳細解釋 – rndy
根據你如何定義_special characters_,你可以使用'tr -d'[:punct:]'' –