To jest interesujące. Zastępowanie $HOME
dla działa tak samo, jak usunięcie cudzysłowów z zadania.
Jeśli umieścisz set -x
u góry tego skryptu, zobaczysz, że wersja z cudzysłowami ustawia nazwę pliku na ~/...
, co jest podane dla -e
. Jeśli usuniesz cytaty, nazwa pliku zostanie ustawiona na rozwiniętą /home/somebody/...
. W pierwszym przypadku widzisz:
+ [ -e ~/... ]
i to się nie podoba. W drugim przypadku, widzisz:
+ [ -e /home/somebody/... ]
i robi pracy.
Jeśli zrobisz to bez zmiennej, widzisz:
+ [ -e /home/somebody/... ]
i tak, to działa.
Po odrobinie dochodzenia, odkryłem, że jest to faktycznie kolejność bash
wykonuje swoje ekspansje. Na stronie atakujących człowieka:
Kolejność ekspansji jest: rozwijanie nawiasów, tyldy, parametr, zmienna i wyrażeń arytmetycznych i polecenia podstawienie (wykonane w lewej do prawej mody), podział na słowa, a ścieżka ekspansja.
Dlatego to nie działa, zmienna jest podstawiona po tyldy ekspansji. Innymi słowy, w punkcie, w którym bash
chce rozwinąć ~
, nie ma żadnego. Dopiero po rozszerzeniu zmiennym słowo zostanie zmienione na ~/...
i po tym nie będzie rozwijania tyldy.
Jedną rzeczą, którą mógł zrobić, to zmienić swoje oświadczenie if
do:
if [[ -e $(eval echo $filename) ]]; then
Ten oceni $ filename argumentu dwukrotnie. Po raz pierwszy (z eval
), nie będzie ~
podczas fazy rozszerzania tyldy, ale $filename
zostanie zmieniony na ~/...
podczas fazy zmiennej ekspansji.
Następnie, podczas drugiej oceny (wykonanej jako część samego if
), w fazie rozszerzania tyldy pojawi się ~
.
Przetestowałem to na moim pliku .profile
i wydaje się, że działa, sugeruję, abyś potwierdził w swoim konkretnym przypadku.
Uważam '~' za wygodną linię komend, której nie należy używać w skryptach. –