Powiedzmy, że chcę zapisać następujące polecenie w zmiennej
cd "/cygdrive/c/Program Files/"
Więc to robię
dir="cd \"/cygdrive/c/Program Files/\""
To powinno przechowywać polecenie, aby przejść do katalogu Program Files, więc kiedy wpisuję $ dir, zabierze mnie do tego katalogu. Aby sprawdzić, czy cytaty zostały poprawnie zmienione, piszę
echo $dir
co daje mi
cd "/cygdrive/c/Program Files/"
Więc wszystko powinno działać dobrze. Jednak kiedy piszę,
$dir
dostaję
bash: cd: "/cygdrive/c/Program: No such file or directory
Co ja robię źle? Używam Cygwin, ale zakładam, że ten problem dotyczy ogólnie bash.
Odpowiedzi:
Krótka odpowiedź: patrz BashFAQ # 050 („Próbuję wstawić polecenie do zmiennej, ale złożone przypadki zawsze zawodzą!”).
Długa odpowiedź: gdy bash analizuje polecenie, analizuje cudzysłowy, zanim zastąpi zmienne; nigdy nie wraca i ponownie analizuje cudzysłowy wartości zmiennych, więc nie robią nic pożytecznego. Użycie echa do sprawdzenia polecenia jest całkowicie mylące, ponieważ pokazuje polecenie po jego przeanalizowaniu; jeśli chcesz zobaczyć, co tak naprawdę jest wykonywane, użyj albo
set -x
poleceń drukowania powłoki w trakcie ich wykonywania, albo użyjprintf "%q " $dir; echo
zamiast zwykłego echa.Jeśli chcesz przechowywać złożone polecenie (np. Ze spacjami lub innymi znakami specjalnymi w „słowach”), musisz umieścić je w tablicy zamiast prostej zmiennej tekstowej, a następnie rozwinąć je za pomocą idiomu „” $ { array [@]} ”, jak to:
Teraz, jeśli celem jest stworzenie łatwego do pisania skrótu, najwyraźniej nie jest to właściwy sposób. Zamiast tego użyj aliasu powłoki lub funkcji:
lub
źródło
Kiedy bash się rozwija
$dir
, wykonuje tylko dzielenie i globowanie słów. Rozszczepienie słowo produkuje trzy słowa:cd
,"/cygdrive/c/Program
iFiles/"
. Następnie polecenie wykonania macd
dwa argumenty;cd
patrzy tylko na pierwszy argument"/cygdrive/c/Program
, który nie jest istniejącym katalogiem.Jeśli chcesz przeprowadzić pełną ocenę powłoki dla zawartości zmiennej, użyj
eval
:Zauważ, że potrzebujesz podwójnych cudzysłowów
$dir
, w przeciwnym razie najpierw zostanie wykonane dzielenie słów, a następnieeval
połączy swoje argumenty spacjami. To by się działało tutaj, ale ogólnie byłoby źle (np. Gdyby w nazwie pliku były dwie kolejne spacje).Jednak ciąg znaków nie jest właściwym sposobem przechowywania polecenia powłoki, które chcesz wykonać. Jeśli nie masz nietypowych wymagań, zamiast tego powinieneś użyć funkcji:
Jeśli jesteś naprawdę zainteresowany w typowania
$dir
do przełącznika do określonego katalogu i nie jest to tylko prosty przykład, ponieważ bash 4, umieścićshopt -s autocd
w swoim.bashrc
i ustawićpo czym możesz wpisać just
"/cygdrive/c/Program Files/"
lub"$dir"
w wierszu poleceń powłoki, aby przejść do tego katalogu. Nadal potrzebujesz podwójnych cudzysłowów$dir
; jeśli ci się to nie podoba, użyj zsh zamiast bash.źródło
Przechowywanie poleceń w zmiennych ogólnie nie jest dobrym pomysłem. Do tego służą funkcje i aliasy.
Zamiast
spróbuj jednego z tych:
lub
lub
Pierwsza forma, przechowująca nazwę katalogu w zmiennej, oznacza trochę więcej pisania, ale jest wyraźniejsza, gdy wykonujesz polecenie, które wykonujesz
cd
. Drugi jest najbliższy temu, co próbujesz osiągnąć. (Nie używam aliasów w bash; nie jestem pewien, jaką przewagę mają one nad funkcjami).EDYTOWAĆ :
I
dir
prawdopodobnie jest to zła nazwa dla aliasu lub funkcji, ponieważ istnieje taka komenda o tej nazwie (jest to w zasadzie wersjals
, przynajmniej jeśli masz GNU coreutils).źródło
Storing commands in variables is generally not a good idea. That's what functions and aliases are for.
Próbować
Ale jeszcze dokładniej:
/programming/4334467/cygwin-using-a-path-variable-containing-a-windows-path-with-a-space-in-it
źródło