Czytałem o tym, że powinienem zacytować zmienne w bash, np. „$ Foo” zamiast $ foo. Jednak podczas pisania skryptu znalazłem przypadek, w którym działa on bez cudzysłowów, ale nie z nimi:
wget_options='--mirror --no-host-directories'
local_root="$1" # ./testdir recieved from command line
remote_root="$2" # ftp://XXX recieved from command line
relative_path="$3" # /XXX received from command line
Ten działa:
wget $wget_options --directory_prefix="$local_root" "$remote_root$relative_path"
Ten nie ma (zwróć uwagę na podwójne cudzysłowy wokół $ wget_options):
wget "$wget_options" --directory_prefix="$local_root" "$remote_root$relative_path"
Jaki jest tego powód?
Czy pierwsza linia to dobra wersja; czy powinienem podejrzewać, że gdzieś jest ukryty błąd, który powoduje takie zachowanie?
Ogólnie, gdzie znajdę dobrą dokumentację, aby zrozumieć, jak działa bash i jego cytowanie? Podczas pisania tego skryptu czuję, że zacząłem pracować na zasadzie prób i błędów zamiast rozumieć zasady.
wget
nie wie, co --mirror --no-host-directories
oznacza (jako jeden argument), ale obsługuje go, gdy jest podzielony na dwa argumenty. Bardzo niewiele programów specjalnie traktuje spacje i cudzysłowy, gdy znajdują się w wektorze argumentów. Problem polega na tym bash
, że i inne powłoki mają być>
bash
, więc możesz sobie wyobrazić, że $a
jest to odpowiednik bezpośredniego pisania jej zawartości. Teraz problem jest oczywisty: a="-a -b"; cmd "$a"
rozwija się cmd "-a -b"
, ale cmd
prawdopodobnie nie wie, co to znaczy. cmd $a
rozszerza się cmd -a -b
, co prawdopodobnie czyni pracę.