Wiem, że prawdopodobnie o to wcześniej pytano, ale nie mogłem tego znaleźć w Google.
Dany
- Jądro Linux
- Brak konfiguracji zmieniających $ HOME
- grzmotnąć
Będzie ~ == $HOME
prawda
echo "~"
i echo "$HOME"
.
~
ani $HOME
. : P
Wiem, że prawdopodobnie o to wcześniej pytano, ale nie mogłem tego znaleźć w Google.
Dany
Będzie ~ == $HOME
prawda
echo "~"
i echo "$HOME"
.
~
ani $HOME
. : P
Odpowiedzi:
Ważne jest, aby zrozumieć, że ~
rozszerzenie jest cechą powłoki (niektórych powłok), nie jest magiczną postacią, niż oznacza katalog domowy, gdziekolwiek jest używany.
Jest rozszerzany (przez powłokę, która jest aplikacją służącą do interpretacji wiersza poleceń), podobnie jak $var
jest rozszerzany do jego wartości w pewnych warunkach, gdy jest używany w linii poleceń powłoki przed wykonaniem polecenia.
Ta funkcja pojawiła się po raz pierwszy w powłoce C pod koniec lat siedemdziesiątych (powłoka Bourne'a nie miała jej, podobnie jak jej poprzedniczka - powłoka Thompson), została później dodana do powłoki Korn (nowsza powłoka zbudowana na powłoce Bourne'a w 80s). Ostatecznie został ustandaryzowany przez POSIX i jest teraz dostępny w większości powłok, w tym takich jak non-POSIX fish
.
Ponieważ jest tak szeroko stosowany w powłokach, niektóre aplikacje inne niż powłoki również rozpoznają go jako oznaczający katalog domowy. Tak jest w przypadku wielu zastosowań w swoich plikach konfiguracyjnych lub ich własnej linii poleceń ( mutt
, slrn
, vim
...).
bash
konkretnie (która jest powłoką projektu GNU i szeroko stosowana w wielu systemach operacyjnych opartych na Linuksie), gdy jest wywoływana jako sh
, przeważnie przestrzega reguł POSIX dotyczących ~
ekspansji, aw obszarach nieokreślonych przez POSIX zachowuje się głównie jak powłoka Korna (z który jest częściowym klonem).
Chociaż $var
jest rozwijany w większości miejsc (z wyjątkiem pojedynczych cudzysłowów), ~
ekspansja, będąca refleksją, jest rozwijana tylko w kilku konkretnych warunkach.
Jest rozwijany, gdy sam argument w kontekstach list, w kontekstach, w których oczekiwany jest ciąg znaków.
Oto kilka przykładów jego rozszerzenia bash
:
cmd arg ~ other arg
var=~
var=x:~:x
(wymagane przez POSIX, używanego dla zmiennych podoba PATH
, MANPATH
...)for i in ~
[[ ~ = text ]]
[[ text = ~ ]]
(rozszerzenie ~
jest traktowane jako wzór w AT&T, ksh
ale nie bash
od 4.0).case ~ in ~) ...
${var#~}
(choć nie w innych powłokach)cmd foo=~
(choć nie przy wywołaniu jako sh
i tylko wtedy, gdy to, co znajduje się po lewej stronie =
ma kształt niecytowanej bash
nazwy zmiennej)cmd ~/x
(oczywiście wymagane przez POSIX)cmd ~:x
(ale nie x:~:x
lub x-~-x
)a[~]=foo; echo "${a[~]} $((a[~]))"
(nie w niektórych innych powłokach)Oto kilka przykładów, w których nie jest rozwinięty:
echo "~" '~'
echo ~@ ~~
(zauważ również, że ~u
ma on na celu rozszerzenie do katalogu domowego użytkownika u
).echo @~
(( HOME == ~ ))
, $(( var + ~ ))
extglob
: case $var in @(~|other))...
(choć case $var in ~|other)
jest OK)../configure --prefix=~
(ponieważ --prefix
nie jest prawidłową nazwą zmiennej)cmd "foo"=~
(w bash
, ze względu na cytaty).sh
: export "foo"=~
, env JAVA_HOME=~ cmd
...Jeśli chodzi o to, do czego się rozwija: ~
sam rozwija się do zawartości HOME
zmiennej lub, gdy nie jest ustawiona, do katalogu domowego bieżącego użytkownika w bazie danych kont (jako rozszerzenie, ponieważ POSIX pozostawia to zachowanie niezdefiniowane).
Należy zauważyć, że w ksh88 i bash
wersjach wcześniejszych niż 4.0 ekspansja tyldy przeszła globbing (generowanie nazw plików) w kontekście list:
$ bash -c 'echo "$HOME"'
/home/***stephane***
$ bash -c 'echo ~'
/home/***stephane*** /home/stephane
$ bash -c 'echo "~"'
~
Nie powinno to stanowić problemu w zwykłych przypadkach.
Pamiętaj, że ponieważ jest rozwinięty, to samo ostrzeżenie ma zastosowanie do innych form rozszerzeń.
cd ~
Nie działa, jeśli $HOME
zaczyna się od -
lub zawiera ..
składniki. Tak więc, chociaż jest bardzo mało prawdopodobne, aby kiedykolwiek coś zmienić, ściśle mówiąc, należy napisać:
cd -P -- ~
Lub nawet:
case ~ in
(/*) cd -P ~;;
(*) d=~; cd -P "./$d";;
esac
(w celu pokrycia wartości $HOME
podobnych -
, +2
...) lub po prostu:
cd
(jak cd
zabierze Cię do katalogu domowego bez żadnych argumentów)
Inne pociski mają bardziej zaawansowane ~
rozszerzenia. Na przykład w zsh
:
~4
, ~-
, ~-2
(W realizacji) wykorzystywane do rozszerzenia katalogi w stosie Directory (miejsc, które już cd
się wcześniej).~something
rozbudowy.W dowolnej wersji Bash na dowolnym systemie, tak . ~
jako termin definiowany jest jako rozszerzenie do:
Wartość $ HOME
więc zawsze będzie taki sam, jak $HOME
dla bieżącej powłoki. Istnieje kilka innych rozszerzeń tyldy, na przykład ~user
dla user
katalogu domowego, ale pojedynczy sam w cudzysłowie ~
zawsze będzie się rozwijał "$HOME"
.
Należy zauważyć, że zachowanie od ~
i $HOME
może być różny w niektórych przypadkach: w szczególności, jeśli $HOME
zawiera spacje (lub inne IFS znaków), a następnie $HOME
(cytowane) wzrośnie do kilku słów, a ~
to zawsze jedno słowo. ~
rozwija się równorzędnie do "$HOME"
(cytowany).
W odniesieniu do twojego konkretnego pytania:
[[ $HOME == ~ ]]
jest zawsze prawdziwe, ponieważ [[
eliminuje dzielenie słów. [[ ~ == $HOME ]
może nie być, jeśli HOME
zawiera znaki pasujące do wzorca , ale [[ ~ == "$HOME" ]]
(tj. cytowane "$HOME"
) jest zawsze prawdziwe. Używanie go w nawiasach pojedynczych może być błędem składniowym dla wartości HOME
zawierających spacje lub znaki specjalne. Dla każdej sensownej konfiguracji katalogu domowego ~
i "$HOME"
są takie same i porównać jako równe.
Stéphane Chazelas zauważył przypadek w komentarzach gdzie ~
i $HOME
podaje różne wartości: jeśli ty unset HOME
, to kiedy użyjesz ~
Bash zadzwoni, getpwuid
aby odczytać wartość z bazy danych haseł. Ten przypadek jest wykluczony z powodu braku zmiany konfiguracji $HOME
, ale wspomnę o tym tutaj dla kompletności.
/bin/sh
może nie być bash
. Nie jestem pewien, czy sh
specyfikacja Posix mówi~
~
. ~
nie było w skorupie Thomsona ani Bourne'a (które w swoim czasie były dostępne jako /bin/sh
). Nie ma go ani nie rc
jest pochodną (gdzie jest używany do czegoś innego)
bash
, jeśli nie HOME
jest ustawiony, ~
rozwija się do katalogu domowego użytkownika z bazy danych passwd. Jest to przypadek, w którym ~
może nie rozwinąć się do wartości $HOME
.
bash
przed bash4 używał globowania po rozwinięciu tyldy (try HOME='/*' bash -c 'echo /*'
). Zwróciłby więc HOME=/*; [ "$HOME" = ~ ]
tam błąd.
get_current_user_info
, który wykorzystuje getpwuid
na wszystkich platformach, ale Tandem .
~
będzie to odpowiednik$HOME
w dowolnym środowisku POSIX; ale mogę się mylić.