2016-11-08 201 views
3

所以我刪除文件名中的特殊字符並用空格替換。除了其中包含單反斜槓的文件外,我已經開始工作了。 注意這些文件在Finder中創建了OS X刪除反斜槓與tr

old_name="testing\this\folder" 
new_name=$(echo $old_name | tr '<>:\\#%|?*' ' '); 

這將導致NEW_NAME被「測試hisolder」 如何我只是刪除了反斜槓,而不是前面的字符?

+1

根據你如何定義_special characters_,你可以使用'tr -d'[:punct:]'' –

回答

3

這將導致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" 
2

使用bash,你可以使用參數擴展:

$ old_name="testing\this\folder" 
$ new_name=${old_name//[<>:\\#%|?*]/ } 
$ echo $new_name 
testing this folder 

有關詳細信息,請參閱猛砸手冊上shell parameter expansion

-1

我認爲你的測試用例丟失了\的正確轉義,所以你並不真正測試包含在字符串中的反斜槓的情況。

這爲我工作:

old_name='testing\\this\\folder' 
new_name=$(echo $old_name | tr '<>:\\#%|?*' ' '); 
echo $new_name 
# testing this folder 
+0

在Bash(這是如何標記問題)中使用默認選項,使用它的'echo'內建,這將保留_both_反斜槓,並且結果字符串在單詞之間會有_2_空格。 (相反,OP的代碼應該按原樣工作。)除此之外,「$ old_name」應該用雙引號。你的轉義只能在打開(隱式或顯式)選項'xpg_echo'的情況下才能起作用,但更好的解決方案是使用'printf'或一個here-string。 – mklement0

2

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
  • 含蓄,如果你運行bash作爲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:]_-' ' ') 

這樣,任何不是字母,數字,_-的字符都將替換爲空格。

+0

感謝您的詳細解釋 – rndy