~ Завжди дорівнює $ HOME


40

Я знаю, що про це, ймовірно, питали і раніше, але я не зміг його знайти в Google.

Дано

  • Ядро Linux
  • Немає конфігурацій, які змінюють $ HOME
  • баш

Чи ~ == $HOMEбуде правдою?


3
Я вважаю так, але це не специфічна для Linux проблема. Швидше, я вважаю, що ~це буде рівнозначно $HOMEв будь-якому середовищі POSIX; але я можу помилитися.
HalosGhost

4
Незважаючи на відповіді нижче ... не завжди. Порівняйте echo "~"і echo "$HOME".
Sparhawk

@Sparhawk Зачекайте, значить, 1 + 1 не є 2? Це змова! Уряд щось приховує від нас! : P
Doorknob

1
@Sparhawk, ви помітите, що ОП насправді не цитувало ані, ~ані $HOME. : P
HalosGhost

2
@HalosGhost Ах, хороший момент. (Також пізніше я помітив, що у відповіді Майкла Гомера згадується "єдине без котирування ~".) У будь-якому випадку, що слід пам’ятати для випадкового читача, як я.
Sparhawk

Відповіді:


46

Що важливо розуміти, це те, що ~розширення є особливістю оболонки (деяких оболонок), це не магічний символ, а значить ваш домашній каталог, де б він не використовувався.

Він розширюється (оболонкою, що є додатком, що використовується для інтерпретації командних рядків), подібно $varдо деяких значень, коли використовується в командному рядку оболонки перед виконанням команди.

Ця особливість вперше з'явилася в C-оболонці в кінці 1970-х (оболонки Борна її не було, як ні у попередника оболонки Томпсона), пізніше була додана до шкаралупи Корна (новішої оболонки, побудованої на оболонці Борна в 80-ті роки). Згодом він був стандартизований POSIX і тепер доступний у більшості оболонок, включаючи такі, що не є POSIX fish.

Оскільки він настільки широко застосовується в оболонках, деякі програми без оболонок також визнають це як домашній каталог. Це справа багатьох додатків в своїх файлах конфігурації або їх власної командного рядка ( mutt, slrn, vim...).

bashконкретно (що є оболонкою проекту GNU і широко використовується у багатьох операційних системах на базі Linux), коли викликається як sh, здебільшого дотримується правил POSIX щодо ~розширення, а в областях, не визначених POSIX, поводиться здебільшого як оболонка Korn (з який це клон частини).

Хоча $varрозширено в більшості місць (крім внутрішніх цитат), ~розширення, що є думкою, розширюється лише за кількох конкретних умов.

Він розширюється, коли за власним аргументом у списках контекстів, у контекстах, де очікується рядок.

Ось кілька прикладів, де це розгорнуто в bash:

  • cmd arg ~ other arg
  • var=~
  • var=x:~:x(вимагається POSIX, використовується для змінних, таких як PATH, MANPATH...)
  • for i in ~
  • [[ ~ = text ]]
  • [[ text = ~ ]](розширення ~сприймається як зразок в AT&T, kshале не bashпочинаючи з 4.0).
  • case ~ in ~) ...
  • ${var#~} (хоча не в деяких інших оболонках)
  • cmd foo=~(хоча не тоді, коли викликається як sh, і лише тоді, коли те, що ліворуч від, =має форму котируваної bashназви змінної)
  • cmd ~/x (вимагається POSIX очевидно)
  • cmd ~:x(але ні x:~:xабо x-~-x)
  • a[~]=foo; echo "${a[~]} $((a[~]))" (не в деяких інших оболонках)

Ось кілька прикладів, коли це не розширено:

  • echo "~" '~'
  • echo ~@ ~~(також зауважте, що ~uпризначений для розширення до домашнього каталогу користувача u).
  • echo @~
  • (( HOME == ~ )), $(( var + ~ ))
  • з extglob: case $var in @(~|other))...(хоча case $var in ~|other)це нормально).
  • ./configure --prefix=~(як --prefixнеправдиве ім'я змінної)
  • cmd "foo"=~bash, через цитати).
  • При виклику як sh: export "foo"=~, env JAVA_HOME=~ cmd...

Щодо того, на що він розширюється: ~самостійно розширюється на вміст HOMEзмінної або коли вона не встановлена, на домашній каталог поточного користувача в базі даних облікових записів (як розширення, оскільки POSIX залишає цю поведінку невизначеною).

Слід зазначити, що в ksh88 та bashверсіях до версії 4.0 розширення tilde зазнало глобалізації (генерація імені файлу) у списках:

$ bash -c 'echo "$HOME"'
/home/***stephane***
$ bash -c 'echo ~'
/home/***stephane*** /home/stephane
$ bash -c 'echo "~"'
~

Це не повинно бути проблемою у звичайних випадках.

Зауважте, що оскільки воно розширене, те саме попередження застосовується як і інші форми розширень.

cd ~

Не працює, якщо $HOMEпочинається з -або містить ..компоненти. Тож хоч і навряд чи колись зміниться, строго кажучи, слід написати:

cd -P -- ~

Або навіть:

case ~ in
  (/*) cd -P ~;;
  (*) d=~; cd -P "./$d";;
esac

(для покриття значень, таких $HOMEяк -, +2...) або просто:

cd

(оскільки cdпереносить вас у домашній каталог без жодних аргументів)

Інші снаряди мають більш досконалі ~розширення. Наприклад, у zshнас є:

  • ~4, ~-, ~-2(Із завершенням) використовується для розширення каталогів в вашому стеку каталогів (місця можна cdраніше).
  • динамічні названі каталоги . Ви можете визначити свій власний механізм, щоб вирішити, як ~somethingйого розширювати.

25

У будь-якій версії Bash в будь-якій системі, так . ~як термін самостійно визначається для розширення:

Значення $ HOME

тож він завжди буде таким же, як і все $HOME, що стосується поточної оболонки. Є дещо інший тильду розширення, такі як ~userдля userдомашнього каталогу «S, але один незгаданих ~сама по собі завжди буде розширюватися "$HOME".

Зверніть увагу , що поведінка в ~і $HOMEможе відрізнятися в деяких випадках: зокрема, якщо $HOMEмістить прогалини (або інші IFS символи), то $HOME(без лапок) буде розширюватися до декількох слів, в той час як ~це завжди одне слово. ~розширюється рівнозначно "$HOME"(цитується).

Що стосується вашого конкретного питання:

[[ $HOME == ~ ]]

завжди правда, тому що [[ пригнічує розбиття слів. [[ ~ == $HOME ]може не бути, якщо в ньому HOMEє символи, що відповідають шаблону , але [[ ~ == "$HOME" ]](тобто, цитується "$HOME") це завжди вірно. Використання його всередині окремих дужок може бути синтаксичною помилкою для значень, HOMEщо містять пробіли або спеціальні символи. Для будь-якої розсудливої конфігурації домашньої директорії ~і "$HOME"є однаковими і вважаються рівними.


Stéphane Chazelas відзначив випадок у коментарях, де ~і $HOMEдають різні значення: якщо ви unset HOME, то при використанні ~Bash зателефонуєте getpwuidпрочитати значення з бази даних паролів. Цей випадок виключається вашою умовою не змінювати конфігурацію $HOME, але я згадаю її тут для повноти.


1
Однак, /bin/shможливо, не буде bash. Я не впевнений, що shспецифікація Posix розповідає про~
Базиле Старинкевич,

1
POSIX вказує ~. ~не було в оболонці Томсона чи Борна (які в свій час були доступні як /bin/sh). Це не в rcйого похідних (де його використовують для чогось іншого)
Stéphane Chazelas

5
У кількох оболонках, включаючи bash, якщо HOMEце не встановлено, ~розширюється на домашній каталог користувача з бази даних passwd. Тож це випадок, коли він ~може не розширюватися до значення $HOME.
Стефан Шазелас

1
Зверніть увагу , що bashперед тим bash4 використовується для виконання підстановки при розширенні тильди (TRY HOME='/*' bash -c 'echo /*'). Тож HOME=/*; [ "$HOME" = ~ ]повернемо туди помилку.
Стефан Шазелас

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.