Dlaczego tylda (~) nie rozwija się, gdy jest używana z argumentem CLI rozpoczynającym się od myślnika?

9

Straciłem kilka godzin, próbując uruchomić serwer VNC (x0vncserver), a klient odmówił połączenia z dziwnym komunikatem, że

No password configured for VNC Auth

Serwer drukuje również ten błąd

 SVncAuth:    opening password file '~/.vnc/passwd' failed

Ok, zmarnowałem dużo czasu, aż zdałem sobie sprawę, że tylda nie została powiększona ani przez powłokę, ani przez x0vncserver. Potem przeprowadziłem te testy

$ echo --PasswordFile=~/.vnc/passwd
--PasswordFile=~/.vnc/passwd

Ale

$ echo PasswordFile=~/.vnc/passwd
PasswordFile=/home/tichomir/.vnc/passwd

Dlaczego? Dlaczego powłoka odmawia rozwinięcia tyldy, jeśli argument zaczyna się od myślnika? Myślałem, że tylda zawsze będzie się rozwijać, dopóki nie będzie cytowana, ale najwyraźniej istnieje inna zasada, która wchodzi w grę?

Tihomir Mitkov
źródło
Powiązane: Rozszerzenie tyldy w zsh
Stéphane Chazelas
Zobacz także: Czy ~ zawsze równa się $ HOME
Stéphane Chazelas

Odpowiedzi:

13

Jest to osobliwość bashpowłoki opisanej w jej instrukcji:

Bash wykonuje także interpretację tyldy dla słów spełniających warunki przypisywania zmiennych (jak opisano powyżej w PARAMETRACH), gdy pojawiają się jako argumenty dla prostych poleceń. Bash tego nie robi, poza wymienionymi powyżej poleceniami deklaracji, gdy jest w trybie posix.

Oznacza to, że bash będzie rozwinąć tyldy w PasswordFile=~/.vnc/passwdciągu, ponieważ jest to argument echo, który wygląda jak przypisanie zmiennej.

Ciąg --PasswordFile=~/.vnc/passwdnie wygląda jak przypisanie zmiennej, ponieważ --PasswordFilenie jest prawidłową nazwą zmiennej.

Zauważ, że bashnie robi tego, gdy pracuje w trybie POSIX, i że inne pociski, jak zsh, kshalbo yashnie rób tego domyślnie ( zshposiada magicequalsubstopcję ekspansji tyldy być wykonywane po nienotowanych jednakowych znaków ( =) choć).

Jeśli chcesz się upewnić, że ścieżka do katalogu domowego bieżącego użytkownika jest poprawnie rozwinięta jako część argumentu polecenia, użyj $HOMEwartości zamiast tyldy:

echo --PasswordFile="$HOME/.vnc/passwd"

W „Polecenia deklaracji wymienione powyżej”, o których mowa w instrukcji są wbudowane w poleceniach alias, declare, typeset, export, readonly, i local.

Kusalananda
źródło
1
+1 | Nie pomyślałbym o tym.
LinuxSecurityFreak
Chociaż uwaga: bash --posix -c '"export" a=~; printf "%s\n" "$a"'wyniki ~.
Stéphane Chazelas
2
Zauważ, ~że rozwijane w to alias a=~byłby błąd zgodności z POSIX (i nie jest użyteczny). Ale tak właśnie zrobił ksh88 (zmieniło się to w ksh93) i prawdopodobnie dlatego robią to także bash, zsh i pdksh. Dlaczego to, yashco zostało napisane przeciwko specyfikacji POSIX, tego nie robi.
Stéphane Chazelas
To jest prawidłowa odpowiedź, ale właściwym podejściem byłoby po prostu podanie argumentu opcji jako osobnego argumentu, a nie połączenie go z opcją za pomocą =jednego argumentu. Zatem rozwinięcie tyldy jest na początku słowa, a pytanie jest dyskusyjne.
JdeBP
1
@JdeBP, jak to się dzieje, w przypadku x0vncserver, x0vncserver --PasswordFile filenie działa, potrzebujesz --PasswordFile=file.
Stéphane Chazelas