代字號(〜)僅在直接出現(且未引用)時才展開到主目錄。當您使用cd "$DESTINATION_FOLDER"
時,字面上使用$DESTINATION_FOLDER
中的字符,包括前導〜。即使您已使用cd $DESTINATION_FOLDER
,〜也會直接插入,儘管$DESTINATION_FOLDER
中的空白和全局元字符已被擴展。因此,在變量中的值上實際上沒有辦法進行波浪擴展。 [注1]
有些人會建議使用eval
,但你必須非常小心。如果$DESTINATION_FOLDER
包含shell元字符,則eval cd "$DESTINATION_FOLDER"
可能會有意想不到的結果。考慮下面的,例如(不其中包含文件的目錄試試這個你在乎):
$ mkdir -p ~/tmp/foo && cd ~/tmp/foo
$ touch a few files
$ ls
a few files
$ x="~/tmp/foo;rm *"
$ # BEWARE!
$ eval cd "$x"
$ # OOPS!
$ ls
$
做到這一點,正確的方法是擴大自己波浪號:
cd "${DESTINATION_FOLDER/#~/$HOME}"
在bash
,${var/pattern/replacement}
產生一個基於$var
的值的字符串,其中pattern
(如果有的話)的第一個實例被替換爲replacement
。如果發生在$var
的開頭,則表單${name/#pattern/replacement}
只能進行替換。pattern
是一個glob,而不是一個正則表達式。
編輯:在評論,Tom Fenech建議,這將是冷靜,如果這是可能的處理~user
以及剛剛~
。同樣,處理bashisms會更酷,如~+2
[注2]。
確實。不幸的是,bash
沒有提供可以代替擴展的內置函數。或者任何其他類型的擴展。所以我認爲有必要使用eval
,但這需要非常小心,如上所述。我認爲這是可以做的最好的是提取只有當它不包含元字符的波浪線前綴,然後才與eval printf %s
展開它,像這樣:
tilde-expand() {
(
shopt -s extglob
if [[ $1 =~ ^~[[:alnum:]_.+-]*(/.*)?$ ]]; then
printf %s "$(eval printf ${1%%/*})${1##*([^/])}"
else
printf %s "$1"
fi
)
}
(上述內容已經不小心被。測試一如往常,eval
應該以最大的謹慎處理,所以請在部署之前仔細檢查)
注:
通常,這並不重要,因爲大多數腳本將輸入作爲參數,而不是從控制檯讀取它們。這樣的腳本可以寫爲:
cdrm() {
cd "$1" && rm -rf readme.md
}
那麼你就可以使用波浪號來調用它:
cdrm ~/Dropbox/myproject/
因爲〜將在調用cdrm
擴大,所以$1
將具有擴展值。
我從來沒有用~+N
波浪擴展,但有可能是人們發現他們必不可少。
這或許可以解決你的問題:https://stackoverflow.com/questions/5748216/bash-problem-with-cd-using-tilde-expansion – ConcurrentHashMap 2014-08-31 17:36:42
是'cd'必要嗎?如果你只是想刪除文件,你可以沒有它。您仍然需要強制bash擴展'〜',可能使用'eval'。改變目錄後,'rm -f readme.md'就足夠了。此外,您可以使用'read -p'提示符:「'以避免單獨的'echo'。 – 2014-08-31 17:54:54