Biorąc pod uwagę ten bash:
PARMS='-rvu'
PARMS+=" --delete --exclude='.git'"
echo $PARMS
rsync ${PARMS} . ${TARGET}
Echo pokazuje ciąg PARMS zgodnie z oczekiwaniami, nie wyświetla się żaden błąd, ale rsync cicho działa tak, jakby opcje dodane przez + = nie istniały. Działa to jednak zgodnie z oczekiwaniami:
PARMS='-rvu'
rsync ${PARMS} --delete --exclude='.git' . ${TARGET}
Chyba spieprzyłem coś z cytatami bashowymi (zawsze miałem z tym problemy), ale nie jestem pewien, co i dlaczego opcje są ignorowane, nawet jeśli łańcuch wydaje się być poprawnie zbudowany.
echo "$PARMS"
irsync "${PARMS}"
...bash
wersji 4.2.25 bez żadnych zmian.Odpowiedzi:
Istnieje różnica między:
i
W pierwszym, pojedyncze cytaty są same w sobie, więc dosłownie są obecne w zastąpionym tekście podanym
rsync
jako argument.rsync
dostaje argument, którego wartość wynosi--exclude='.git'
. W drugim przypadku pojedyncze cudzysłowy są interpretowane przez powłokę w momencie ich pisania, ponieważ same nie są wewnątrz cudzysłowów irsync
można je zobaczyć--exclude=.git
.W tym przypadku nie potrzebujesz w ogóle pojedynczych cudzysłowów -
.git
to samo w sobie poprawne słowo powłoki, bez znaków specjalnych, więc możesz używać go dosłownie w poleceniu.Jednak dla tego rodzaju rzeczy lepsza jest tablica :
Tworzy to twoje polecenie jako osobne słowa, z dowolnym cytatem, który chcesz interpretować w momencie pisania wiersza tablicy.
"${PARMS[@]}"
rozwija się do każdego wpisu w tablicy jako osobny argument, nawet jeśli sam argument zawiera w sobie znaki specjalne lub spacje, więcrsync
widzisz, co napisałeś tak, jak chciałeś.źródło
bash
wykonano dzielenie słów po${PARMS}
rozszerzeniu. Więc pojedynczy cytat został również zinterpretowany przez powłokę.\
,'
i"
., Które nie wynikają z jednego z powyższych rozszerzeń są usuwane” „powyżej rozszerzeń” obejmuje rozszerzenie parametrów, które wykonuje rozszerzenie${PARMS}
.IFS
(zazwyczaj spacją), nie musisz ich cytować. Jeśli tak, to masz pecha, chyba że zhakujesz coś razemeval
- to ogólnie jest trochę mylne, a tablice są właściwym sposobem na poradzenie sobie z tym.Oprócz odpowiedzi @Michael Homer , możesz użyć
bash
funkcji eval :źródło
eval
.