Я знаю, що про це, ймовірно, питали і раніше, але я не зміг його знайти в Google.
Дано
- Ядро Linux
- Немає конфігурацій, які змінюють $ HOME
- баш
Чи ~ == $HOME
буде правдою?
echo "~"
і echo "$HOME"
.
~
ані $HOME
. : P
Я знаю, що про це, ймовірно, питали і раніше, але я не зміг його знайти в Google.
Дано
Чи ~ == $HOME
буде правдою?
echo "~"
і echo "$HOME"
.
~
ані $HOME
. : P
Відповіді:
Що важливо розуміти, це те, що ~
розширення є особливістю оболонки (деяких оболонок), це не магічний символ, а значить ваш домашній каталог, де б він не використовувався.
Він розширюється (оболонкою, що є додатком, що використовується для інтерпретації командних рядків), подібно $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
його розширювати.У будь-якій версії 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
, але я згадаю її тут для повноти.
/bin/sh
можливо, не буде bash
. Я не впевнений, що sh
специфікація Posix розповідає про~
~
. ~
не було в оболонці Томсона чи Борна (які в свій час були доступні як /bin/sh
). Це не в rc
його похідних (де його використовують для чогось іншого)
bash
, якщо HOME
це не встановлено, ~
розширюється на домашній каталог користувача з бази даних passwd. Тож це випадок, коли він ~
може не розширюватися до значення $HOME
.
bash
перед тим bash4 використовується для виконання підстановки при розширенні тильди (TRY HOME='/*' bash -c 'echo /*'
). Тож HOME=/*; [ "$HOME" = ~ ]
повернемо туди помилку.
get_current_user_info
, який використовує getpwuid
на всіх платформах , але Тандем .
~
це буде рівнозначно$HOME
в будь-якому середовищі POSIX; але я можу помилитися.