Разница между $ HOME и ~

31

$HOMEи ~обычно ссылаются на одно и то же. То есть они представляют собой путь к «домашнему» каталогу пользователя, который имеет общую форму «/ home / userName».

Когда, если вообще, они не относятся к одному и тому же каталогу?

H2ONaCl
источник
11
Это ~зависит от оболочки, а $ HOME - нет.
Кульфи
Очень многое связано с unix.stackexchange.com/a/400715/85039
Сергей Колодяжный

Ответы:

45

И то, $HOMEи другое ~указывает на одну и ту же папку, домашнюю папку текущего пользователя, но оба они очень разные.

  • $HOMEявляется переменной среды , которая устанавливается , чтобы содержать домашнюю папку текущего пользователя.
  • ~является символом расширения оболочки , т. е. одним из символов, который обрабатывается перед выполнением фактической команды. ~само по себе расширяется до значения $ HOME. ~nemoрасширяется до домашнего каталога пользователя nemo. Символ расширения оболочки - это символ (или пара символов), который обрабатывается / интерпретируется оболочкой для создания фактической команды. Другой пример символа расширения оболочки - *это расширение имен файлов.
ванадий
источник
1
~расширяется до $ HOME или% APPDATA% в Windows. Если они не определены, он будет искать путь в «базе паролей» (что обычно означает /etc/passwd, но может быть LDAP или какой-либо другой источник данных). Около 20 лет назад вы могли быть предупреждены, что $ HOME может быть не установлен на некоторых машинах, хотя ~гарантированно расширится до чего-то.
Мирек Длугош
Эта разница заметна в таких программах, как make, когда вам нужно знать, какая из двух вам нужна
D. Ben Knoble
3
@ MirekDługosz По крайней мере на git bash в Windows, ~расширяется до $HOME(равно $HOMEPATH), а не $APPDATA. И на cmd.exe, ~не расширяется.
Гайд
1
@vanadium HOME- это переменная окружения (концепция ОС, например , в оболочках sh, установленная с помощью exportили declare -x), а не переменная оболочки (определение которой полностью зависит от оболочки, но в оболочках sh она обычно устанавливается с foo=valueили с setили в нескольких других пути).
Гайд
1
@hyde Я сформулировал это неправильно. bash проверит наличие $ HOME, если оно не установлено, то будет проверять наличие% APPDATA%, но только в Windows; если он не установлен, он будет искать «базу паролей». См. Git.savannah.gnu.org/cgit/bash.git/tree/lib/readline/…
Мирек Длугош
17

Один из их отличий заключается в том, как оболочка Bash преобразует их в "кавычках.

Если вы используете echoтак без кавычек, то ~и $HOMEполучите тот же эффект:

$ echo ~
/home/elias
$ echo $HOME
/home/elias

Однако с "кавычками вокруг них результат отличается:

$ echo "~"
~
$ echo "$HOME"
/home/elias
Элиас
источник
13

~расширяется только как часть префикса тильды, который по определению должен начинаться с начала слова. Кроме того, поскольку это когда-то было частью глобальных шаблонов, оно ~не будет работать внутри двойных кавычек. Таким образом, "~"или a~bприведет к буквальному значению ~сохранения.

Один ~(или ~сопровождаемый /) расширится до дома текущего пользователя:

$ echo ~/.ssh
/home/user/.ssh

За ~ним следует имя пользователя, которое развернется в домашнюю папку этого пользователя:

$ echo ~root/.ssh
/root/.ssh

За ~ним следует a +или a -и необязательный номер, который расширится до элементов стека каталогов :

$ cd /etc
$ echo ~+0
/etc

$HOMEэквивалент одного ~, который вместо этого следует правилам синтаксиса для переменных. Например, он раскрывается внутри двойных кавычек, может быть не установлен, и к нему могут применяться операнды манипуляции со строками .

Дмитрий Григорьев
источник
3

Это во многом зависит от того, что делает расширение. В bash ~это удобный способ получить домашний каталог, не вызывая расширения имени файла или разделения слов, даже если он не заключен в кавычки. Например:

$ HOME='/*'
$ echo $HOME
/bin /boot /dev /etc /home /lib /lib64 /media /mnt /opt /proc /root /run /sbin /srv /sys /tmp /usr /var
$ echo ~
/*

Или:

$ HOME='/ a b'
$ printf "|%s|\n" $HOME ~
|/|
|a|
|b|
|/ a b|

Так что, если вы по каким-то причинам боретесь с кавычками (в этом случае вам следует по-настоящему переосмыслить все это, проще бороться со свиньями), это ~может быть более удобным.


В другом месте, например, в Python, ~и $HOMEдолжны быть расширены с помощью различных функций . В некоторых других местах допускаются переменные и не допускается использование другого синтаксиса оболочки, например подстановочных знаков или раскрытия тильды (например ~/.pam_environment, который имеет специальный синтаксис для раскрытия переменных). Тем не менее, другие места допускают расширение тильды в качестве исключения (например, systemd ), но вместо использования запрашивают базу данных passwd напрямую $HOME.

Homeboy
источник
Другое большое отличие, которое вы показываете здесь, но не упоминаете, состоит в том, что вы можете изменить значение $HOME, но вы не можете (напрямую) изменить значение ~.
Джо
Поэтому я спросил, когда делать $HOMEи ~не ссылаться на одну и ту же вещь - они обычно делают по умолчанию - и затем вы сознательно назначаете переменную среды, чтобы они не ссылались на одну и ту же вещь. Это хорошая демонстрация, но излишне запутанная.
H2ONaCl
1

$ HOME / более вероятно будет работать в стандартном POSIX.2 Bourne / bin / sh, поскольку расширение тильды является расширением, найденным в BSD csh tcsh GNU bash и других.

Если вы хотите написать сценарии, переносимые на busybox или dash или BSD sh, инвестируйте в дополнительные буквы, чтобы не потерпеть крах с ~ /: в некоторых системах такой файл или каталог отсутствуют.

Я также нахожу $ HOME / более читабельным.

Роман Чиборра
источник
В скрипте важны читабельность и видимость. Возможно, именно поэтому мои сценарии используются $HOMEи используются редко ~. Моя бывшая личность, вероятно, знала это.
H2ONaCl