題 當目錄名稱包含空格時,使用bash變量轉到目錄不起作用


假設我想將以下命令存儲在變量中

cd "/cygdrive/c/Program Files/"

所以我這樣做

dir="cd \"/cygdrive/c/Program Files/\""

那應該存儲命令導航到Program Files目錄,所以當我輸入$ dir時它會把我帶到那個目錄。要檢查報價是否已正確轉義,我輸入

echo $dir

這給了我

cd "/cygdrive/c/Program Files/"

所以一切都應該工作正常。但是,當我輸入時,

$dir

我明白了

bash: cd: "/cygdrive/c/Program: No such file or directory

我究竟做錯了什麼?我正在使用Cygwin,但我認為這個問題一般適用於bash。


11
2017-11-19 20:44


起源


嘗試刪除目錄名稱周圍的引號,然後使用反斜杠轉義空格。 - Mike Fitzpatrick


答案:


簡短的回答:看 BashFAQ#050 (“我正在嘗試將命令放在變量中,但複雜的情況總是失敗!”)。

答案很長:當bash解析命令時,它會在替換變量之前解析引號;它永遠不會返回並重新解析變量值中的引號,因此它們最終沒有做任何有用的事情。使用echo來檢查命令是完全誤導的,因為它顯示了命令  它被解析了;如果你想看看真正被執行的是什麼 set -x 在執行或使用時打印shell打印命令 printf "%q " $dir; echo 而不是普通的迴聲。

如果你想存儲一個複雜的命令(即在“單詞”中有空格或其他特殊字符的命令),你需要把它放在一個數組而不是一個簡單的文本變量中,然後用成語`“$ {展開它數組[@]}“,像這樣:

dir=(cd "/cygdrive/c/Program Files/")
"${dir[@]}"

現在,如果目的是製作一種易於打字的速記,那麼這顯然不是可行的方法。使用shell別名或函數代替:

alias dir='cd "/cygdrive/c/Program Files/"'
dir

要么

dir() { cd "/cygdrive/c/Program Files/"; }
dir

8
2017-11-19 21:15





當bash擴展時 $dir,它只對它執行分詞和通配。單詞分裂產生三個單詞: cd"/cygdrive/c/Program 和 Files/"。然後執行的命令是 cd 有兩個論點; cd 只看第一個參數, "/cygdrive/c/Program,這不是現有目錄。

如果要對變量的內容執行完整shell評估,請使用 eval

eval "$dir"

請注意,您需要雙引號 $dir否則將首先執行分詞 eval 將它的參數與空格連接起來。這可能會在這裡起作用,但一般會變壞(例如,如果文件名中有兩個連續的空格)。

但是,字符串不是存儲要執行的shell命令的正確方法。除非你有不尋常的要求,否則你應該使用一個函數:

dir () {
  cd "/cygdrive/c/Program Files/"
}

如果你真的對打字很感興趣 $dir 切換到特定目錄,這不僅僅是一個簡單的例子,因為bash 4,put shopt -s autocd 在你的 .bashrc 並設置

dir="/cygdrive/c/Program Files/"

之後你可以輸入 "/cygdrive/c/Program Files/" 要么 "$dir" 在shell提示符下切換到該目錄。你還需要雙引號 $dir;如果您不喜歡,請使用zsh而不是bash。


7
2017-11-19 21:15





將命令存儲在變量中通常不是一個好主意。這就是函數和別名的用途。

而不是

dir="cd \"/cygdrive/c/Program Files/\""

嘗試其中一個:

dir="/cygdrive/c/Program Files"
...
cd "$dir"

要么

dir() { cd "/cygdrive/c/Program Files"; }
dir

要么

alias dir='cd "/tmp/Program Files"'
...
dir

第一種形式,將目錄的名稱存儲在變量中,意味著更多的輸入,但是當您執行命令時,它更清晰 cd。第二個最接近你想要完成的事情。 (我不會在bash中使用別名;我實際上並不確定它們對函數有什麼好處。)

編輯:

dir 可能是別名或函數的壞名稱,因為該名稱存在一個現有命令(它基本上是一個版本的 ls,至少如果你有GNU coreutils)。


6
2017-11-19 21:38



upvote for Storing commands in variables is generally not a good idea. That's what functions and aliases are for. - Rob


嘗試

bash$ echo  'This   is   "a     long"  line' > mylist
bash$ echo @mylist
@mylist
bash$ cmd
c:\> c:\cygwin\bin\echo @mylist
This is a     long line

但更具體地說:

https://stackoverflow.com/questions/4334467/cygwin-using-a-path-variable-containing-a-windows-path-with-a-space-in-it


-1
2017-11-19 21:02