~ Equivale sempre a $ HOME


40

So che probabilmente è stato chiesto prima, ma non sono riuscito a trovarlo con Google.

Dato

  • Kernel Linux
  • Nessuna configurazione che cambia $ HOME
  • bash

Sarà ~ == $HOMEvero?


3
Credo di si, ma questo non è un problema specifico di Linux. Piuttosto, credo ~che sarà equivalente a $HOMEin qualsiasi ambiente POSIX; Ma potrei sbagliarmi.
HalosGhost,

4
Nonostante le risposte di seguito ... non sempre. Confronta echo "~"e echo "$HOME".
Sparhawk,

@Sparhawk Aspetta, quindi 1 + 1 non è 2? È una cospirazione! Il governo ci sta nascondendo qualcosa! : P
Doorknob,

1
@Sparhawk, noterai che l'OP in realtà non ha citato né il ~o $HOME. : P
HalosGhost,

2
@HalosGhost Ah, buon punto. (Inoltre, in seguito ho notato che Michael Homer risposta di menziona "un singolo non citato" ~.) Comunque, qualcosa da tenere a mente per il lettore occasionale, come me.
Sparhawk,

Risposte:


46

La cosa importante da capire è che l' ~espansione è una caratteristica della shell (di alcune shell), non è un personaggio magico che significa la tua home directory ovunque venga usata.

Viene espanso (dalla shell, che è un'applicazione utilizzata per interpretare le righe di comando), come $varviene espanso al suo valore in alcune condizioni se utilizzato in una riga di comando della shell prima dell'esecuzione del comando.

Quella funzionalità apparve per la prima volta nella shell C alla fine degli anni '70 (la shell Bourne non ce l'aveva, né il suo predecessore la shell Thompson), fu successivamente aggiunta alla shell Korn (una shell più recente costruita sulla shell Bourne nella anni 80). Alla fine è stato standardizzato da POSIX ed è ora disponibile nella maggior parte delle shell, incluse quelle non POSIX come fish.

Dato che è molto diffuso nelle shell, alcune applicazioni non shell lo riconoscono anche come home directory. Questo è il caso di molte applicazioni nelle loro file di configurazione o la loro propria linea di comando ( mutt, slrn, vim...).

bashin particolare (che è il guscio del progetto GNU e ampiamente utilizzati in molti sistemi operativi basati su Linux), quando invocata sh, segue lo più le regole POSIX circa ~espansione, e in aree non indicate da POSIX, si comporta principalmente come shell Korn (di di cui è un clone parziale).

Mentre $varviene espanso nella maggior parte dei luoghi (tranne all'interno di virgolette singole), l' ~espansione, essendo un ripensamento viene espansa solo in alcune condizioni specifiche.

Si espande quando è sul proprio argomento in contesti di elenchi, in contesti in cui è prevista una stringa.

Ecco alcuni esempi di dove è espanso bash:

  • cmd arg ~ other arg
  • var=~
  • var=x:~:x(richiesto da POSIX, utilizzato per variabili come PATH, MANPATH...)
  • for i in ~
  • [[ ~ = text ]]
  • [[ text = ~ ]](l'espansione ~dell'essere preso come modello in AT&T kshma non bashdalla 4.0).
  • case ~ in ~) ...
  • ${var#~} (anche se non in altre conchiglie)
  • cmd foo=~(anche se non quando viene invocato come sh, e solo quando ciò che è a sinistra del =è a forma di non quotatobash nome di variabile )
  • cmd ~/x (richiesto ovviamente da POSIX)
  • cmd ~:x(ma non x:~:xox-~-x )
  • a[~]=foo; echo "${a[~]} $((a[~]))" (non in alcune altre conchiglie)

Ecco alcuni esempi in cui non è espanso:

  • echo "~" '~'
  • echo ~@ ~~(nota anche che ~uè destinato ad espandersi nella home directory dell'utente u).
  • echo @~
  • (( HOME == ~ )), $(( var + ~ ))
  • con extglob: case $var in @(~|other))...(sebbenecase $var in ~|other) sia OK).
  • ./configure --prefix=~(poiché --prefixnon è un nome di variabile valido)
  • cmd "foo"=~ (nel bash , a causa delle virgolette).
  • Quando invocato come sh: export "foo"=~,env JAVA_HOME=~ cmd ...

Per quanto riguarda ciò che si espande a: ~ da solo si espande nel contenuto della HOMEvariabile, o quando non è impostato, nella directory home dell'utente corrente nel database degli account (come estensione poiché POSIX lascia quel comportamento indefinito).

Va notato che in ksh88 e nelle bashversioni precedenti alla 4.0, l'espansione tilde è stata sottoposta a globbing (generazione del nome file) in contesti di elenco:

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

Questo non dovrebbe essere un problema nei soliti casi.

Si noti che, poiché è espanso, lo stesso avviso si applica ad altre forme di espansioni.

cd ~

Non funziona se $HOMEinizia con -o contiene ..componenti. Quindi, anche se è molto improbabile che faccia alcuna differenza, a rigor di termini, si dovrebbe scrivere:

cd -P -- ~

O anche:

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

(per coprire valori $HOMEcome -, +2...) o semplicemente:

cd

(come cdti porta alla tua home directory senza alcun argomento)

Altre shell hanno ~espansioni più avanzate . Ad esempio, inzsh , abbiamo:

  • ~4, ~-,~-2 (Con il completamento) utilizzato per espandere le directory nel vostro stack delle directory (i luoghi che hai cda prima).
  • directory con nome dinamico . È possibile definire il proprio meccanismo per decidere come ~somethingviene espanso.

25

In qualsiasi versione di Bash su qualsiasi sistema, sì . ~come termine da solo è definito per espandersi a:

Il valore di $ HOME

quindi sarà sempre lo stesso di qualunque cosa $HOMEsia per la shell corrente. Ci sono molte altre espansioni di tilde, come ~userper userla home directory, ma un singolo non quotato ~da solo si espanderà sempre "$HOME".

Si noti che il comportamento di ~e $HOMEpuò essere diverso in alcuni casi: in particolare, se $HOMEcontiene spazi (o altri caratteri IFS ), allora $HOME(non quotato) si espanderà a più parole, mentre ~è sempre una singola parola. ~si espande in modo equivalente a "$HOME"(citato).

Per quanto riguarda la tua domanda specifica:

[[ $HOME == ~ ]]

è sempre vero, perché [[ sopprime la divisione delle parole. [[ ~ == $HOME ]potrebbe non essere se HOMEcontiene caratteri di corrispondenza del modello , ma [[ ~ == "$HOME" ]](ovvero, citato "$HOME") è sempre vero. L'uso all'interno di parentesi singole può essere un errore di sintassi per valori HOMEcontenenti spazi o caratteri speciali. Per qualsiasi configurazione di directory home ragionevole ~e "$HOME"sono uguali e confronta come uguali.


Stéphane Chazelas ha notato un caso nei commenti dove ~e $HOMEfornisce valori diversi: se tu unset HOME, allora quando usi ~Bash chiamerai getpwuidper leggere un valore dal database delle password. Questo caso è escluso dalla tua condizione di non modificare la configurazione $HOME, ma lo citerò qui per completezza.


1
Tuttavia, /bin/shpotrebbe non esserlo bash. Non sono sicuro che le shspecifiche Posix ~
parlino

1
Specifica POSIX ~. ~non era nella shell Thomson o Bourne (che ai loro tempi erano disponibili come /bin/sh). Non è in rco suoi derivati ​​(dove viene utilizzato per qualcos'altro)
Stéphane Chazelas,

5
In alcune shell tra cui bash, se HOMEnon è impostato, si ~espande nella directory home dell'utente dal database passwd. Quindi questo è un caso in cui ~potrebbe non espandersi al valore di $HOME.
Stéphane Chazelas,

1
Si noti che bashprima di bash4 era utilizzato per eseguire il globbing sull'espansione della tilde (provare HOME='/*' bash -c 'echo /*'). Quindi HOME=/*; [ "$HOME" = ~ ]restituirebbe un errore lì.
Stéphane Chazelas,

4
@cuonglm Ho controllato il codice sorgente. Alla fine chiama get_current_user_info , che utilizza getpwuidsu tutte le piattaforme tranne Tandem .
Michael Homer,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.