2014-08-31 84 views
1

我試圖創建一個非常簡單的bash腳本,執行以下操作:CD在bash腳本的文件夾名稱以符號(〜)

  • 輸入用戶輸入一個項目文件夾
  • 設置在一個變量
  • CD輸入到文件夾中的輸入值
  • 刪除readme.md文件

從我來我讀過周圍了這樣的:我進入

#!/bin/bash 

echo "Enter the project folder path:" 
read -e DESTINATION_FOLDER 

cd "$DESTINATION_FOLDER" 
rm -rf "$DESTINATION_FOLDER/readme.md" 

該文件夾的路徑是

〜/ Dropbox的/ myproject的

而我得到的錯誤是下面的一個。但是,該文件夾存在,我可以使用cd命令手動訪問它。

./cleanup.sh: line 6: cd: ~/Dropbox/myproject/: No such file or directory 

任何人都可以請指出我做錯了什麼?

+0

這或許可以解決你的問題:https://stackoverflow.com/questions/5748216/bash-problem-with-cd-using-tilde-expansion – ConcurrentHashMap 2014-08-31 17:36:42

+0

是'cd'必要嗎?如果你只是想刪除文件,你可以沒有它。您仍然需要強制bash擴展'〜',可能使用'eval'。改變目錄後,'rm -f readme.md'就足夠了。此外,您可以使用'read -p'提示符:「'以避免單獨的'echo'。 – 2014-08-31 17:54:54

回答

3

代字號()僅在直接出現(且未引用)時才展開到主目錄。當您使用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應該以最大的謹慎處理,所以請在部署之前仔細檢查)


注:

  1. 通常,這並不重要,因爲大多數腳本將輸入作爲參數,而不是從控制檯讀取它們。這樣的腳本可以寫爲:

    cdrm() { 
        cd "$1" && rm -rf readme.md 
    } 
    

    那麼你就可以使用波浪號來調用它:

    cdrm ~/Dropbox/myproject/ 
    

    因爲將在調用cdrm擴大,所以$1將具有擴展值。

  2. 我從來沒有用~+N波浪擴展,但有可能是人們發現他們必不可少

+0

關於擴展的有趣想法,如果它也適用於'〜user',那將會是錦上添花。你在第二段中說過的話對我不起作用 - 試着'讀一下;使用輸入'〜'回顯$ a'。 – 2014-08-31 18:32:09

+0

偉大的解決方案和解釋,謝謝! – 2014-08-31 18:44:12

+0

您的第二段不正確,變量擴展如下代碼段擴展,因此使用'cd $ FOO','$ FOO'中的代字號不會被擴展。 – user2719058 2014-08-31 19:43:26

2

這是在您將某些東西輸入到交互式shell中時將~擴展到您的主目錄中的shell。它不會從腳本工作。

您需要輸入完整路徑才能使其正常工作。 (當然,它可以是相對路徑。)

有關如何在bash腳本中擴展代字號的this SO question

+1

但是你可以使用'eval cd「$ DESTINATION_FOLDER」'得到它的工作。 – ConcurrentHashMap 2014-08-31 17:37:29

相關問題