Почему тильда (~) не раскрывается при использовании с аргументом CLI, начинающимся с тире?

9

Я потерял пару часов, пытаясь запустить сервер VNC (x0vncserver), и клиент отказался подключиться со странным сообщением, которое

No password configured for VNC Auth

Сервер также печатает эту ошибку

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

Хорошо, я потратил много времени, пока не понял, что тильда не была расширена ни оболочкой, ни x0vncserver. Затем я провел эти тесты

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

Но

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

Это почему? Почему оболочка отказывается расширять тильду, если аргумент начинается с тире? Я думал, что тильда всегда будет расширяться до тех пор, пока она не будет указана, но, видимо, есть еще одно правило, которое вступает в игру?

Тихомир Митков
источник
Связанный: Расширение тильды в zsh
Стефан
Смотрите также: всегда ли ~ равно $ HOME
Стефан

Ответы:

13

Это особенность bashоболочки, описанная в ее руководстве:

Bash также выполняет раскрытие тильды для слов, удовлетворяющих условиям назначения переменных (как описано выше в разделе ПАРАМЕТРЫ), когда они появляются в качестве аргументов простых команд. Bash не делает этого, за исключением команд объявления, перечисленных выше, в режиме posix.

Это означает, что bash это расширит тильду в вашей PasswordFile=~/.vnc/passwdстроке, так как это аргумент, echoкоторый выглядит как присваивание переменной.

Строка --PasswordFile=~/.vnc/passwdне похожа на присвоение переменной, поскольку строка --PasswordFileне является допустимым именем переменной.

Обратите внимание, что bashэтого не происходит при работе в режиме POSIX, и что другие оболочки, например zsh, kshили yashне делают этого по умолчанию ( хотя zshесть magicequalsubstопция для раскрытия тильды после знаков равенства без кавычек ( =), хотя).

Если вы хотите убедиться, что путь к домашнему каталогу текущего пользователя правильно раскрыт как часть аргумента команды, используйте $HOMEзначение вместо тильды:

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

«Декларация команды , перечисленные выше» , упомянутые в руководстве, встроенные команды alias, declare, typeset, export, readonly, и local.

Кусалананда
источник
1
+1 | Я бы не подумал об этом.
LinuxSecurityFreak
Хотя обратите внимание: bash --posix -c '"export" a=~; printf "%s\n" "$a"'выводы ~.
Стефан
2
Обратите внимание, ~что расширение в alias a=~было бы ошибкой соответствия POSIX (и это не полезно). Но именно так ksh88 сделал это (что изменилось в ksh93) и, вероятно, поэтому bash, zsh и pdksh делают это также. Почему то, yashчто было написано против спецификации POSIX, этого не делает.
Стефан
Это правильный ответ, но правильный подход состоял бы в том, чтобы просто указать аргумент опции как отдельный аргумент, а не объединить его с использованием опции =в один аргумент. Тогда расширение тильды находится в начале слова, и вопрос спорный.
JdeBP
1
@JdeBP, как это бывает, в случае x0vncserver, x0vncserver --PasswordFile fileне работает, вам нужно --PasswordFile=file.
Стефан