Est-ce que ~ égalent toujours $ HOME

Je sais que cela a probablement été demandé avant, mais je ne pouvais pas le find avec Google.

Donné

  • Noyau Linux
  • Aucune configuration qui change $ HOME
  • bash

Est-ce que ~ == $HOME sera vrai?

Ce qui est important à comprendre, c'est que ~ expansion est une caractéristique de la coquille (de certains coquillages), ce n'est pas un caractère magique que signifie votre directory de base où il est utilisé.

Il est développé (par le shell, qui est une application utilisée pour interpréter les lignes de command), comme $var est étendu à sa valeur dans certaines conditions lorsqu'il est utilisé dans une command line shell avant l'exécution de la command.

Cette caractéristique est apparue dans la coquille C à la fin des années 1970 (la coquille de Bourne ne l'avait pas, ni son prédécesseur la coquille de Thompson), a ensuite été ajoutée à la coquille de Korn (une coquille plus récente construite sur la coquille Bourne dans le 80s). Il a finalement été standardisé par POSIX et est maintenant disponible dans la plupart des coquilles, y compris les non-POSIX comme le fish .

Comme il est largement utilisé dans les shells, certaines applications non-shell le reconnaissent également comme étant le directory de base. C'est le cas de nombreuses applications dans leurs files de configuration ou leur propre command line ( mutt , slrn , vim …).

bash spécifiquement (qui est la coquille du projet GNU et largement utilisé dans de nombreux systèmes d'exploitation Linux), lorsqu'il est appelé sh , suit la plupart du time les règles POSIX sur ~ expansion, et dans des zones non spécifiées par POSIX shell (dont il est un clone partie), mais voir le bug mentionné ci-dessous.

Alors que $var est étendu dans la plupart des endroits (sauf à l'intérieur des guillemets simples), ~ expansion, étant une reflection après coup est seulement développée dans quelques conditions spécifiques.

Il est développé lorsque sur son propre argument dans les contexts de list, dans les contexts où une string est attendue.

Voici quelques exemples où il est développé dans bash :

  • cmd arg ~ other arg
  • var=~
  • var=x:~:x (requirejs par POSIX, utilisé pour des variables comme PATH , MANPATH …)
  • for i in ~
  • [[ ~ = text ]]
  • [[ text = ~ ]] ( ~ étant pris comme motif dans ksh mais pas bash ).
  • case ~ in ~) ...
  • ${var#~} (mais pas dans d'autres coquilles)
  • cmd foo=~ (mais pas quand il est invoqué comme sh , et seulement quand ce qui est à gauche du = est en forme comme un nom de variable bash non bash )
  • cmd ~/x (requirejs par POSIX évidemment)
  • cmd ~:x (mais pas x:~:x ou x-~-x )
  • a[~]=foo; echo "${a[~]} $((a[~]))" a[~]=foo; echo "${a[~]} $((a[~]))" (pas dans d'autres coquilles)

Voici quelques exemples où il n'est pas développé:

  • echo "~" '~'
  • echo ~@ ~~ (notez également que ~u est destiné à s'étendre au directory home de l'user u ).
  • echo @~
  • (( HOME == ~ )) , $(( var + ~ ))
  • avec extglob : case $var in @(~|other))... (bien que le case $var in ~|other) soit OK).
  • ./configure --prefix=~ (car --prefix n'est pas un nom de variable valide)
  • cmd "foo"=~ (en bash , à cause des guillemets).
  • quand invoqué comme sh : export "foo"=~ , env JAVA_HOME=~ cmd

En ce qui concerne le contenu de la variable HOME , le contenu de la variable HOME n'est pas défini dans le directory de base de l'user actuel de la database du count (en tant qu'extension puisque POSIX laisse ce comportement indéfini).

Il est à noter que dans les versions bash antérieures à 4.0, l'expansion tilde a été soumise à un process de génération de nom de file dans les contexts de list:

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

Cela ne devrait pas être un problème dans les cas habituels.

Notez que parce qu'il est développé, le même avertissement s'applique que d'autres forms d'extensions.

 cd ~ 

Ne fonctionne pas si $HOME commence par - ou contient des composants. Donc, même s'il est très peu probable de faire une différence à proprement parler, il faut écrire:

 cd -P -- ~ 

Ou même:

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

(pour couvrir les valeurs de $HOME comme - , +2 …) ou simplement:

 cd 

(car cd vous emmène dans votre directory personnel sans aucun argument)

D'autres coquilles ont des extensions plus avancées. Par exemple, dans zsh , nous avons:

  • ~4 , ~- , ~-2 (avec complétion) utilisé pour développer les directorys de votre stack de directorys (les endroits où vous avez cd auparavant).
  • directorys dynamics nommés . Vous pouvez définir votre propre mécanisme pour décider comment ~something est développé.

Dans n'importe quelle version de Bash sur n'importe quel système, oui . ~ comme un terme à lui seul est défini pour étendre à:

La valeur de $ HOME

donc il sera toujours le même que tout ce que $HOME est au shell actuel. Il existe plusieurs autres expansions de tilde, telles que ~user directory personnel de l' ~user pour l' user , mais un seul ~ guillemets ~ s'étendra toujours à "$HOME" .

Notez que le comportement de ~ et de $HOME peut être différent dans certains cas: en particulier, si $HOME contient des espaces (ou d'autres caractères IFS ), alors $HOME (sans guillemets) sera étendu à plusieurs mots alors que ~ est toujours un mot . ~ développe de manière équivalente à "$HOME" (cité).

En ce qui concerne votre question spécifique:

 [[ $HOME == ~ ]] 

est toujours vrai, car [[ supprime la division de mots. [[ ~ == $HOME ] ne contienne pas de motifs , mais que [[ ~ == "$HOME" ]] (c.-à-d., "$HOME" ) est toujours vrai. L'utiliser à l'intérieur de simples parenthèses peut être une erreur de syntaxe pour les valeurs de HOME contenant des espaces ou des caractères spéciaux. Pour toute configuration de directory de base sensible ~ et "$HOME" sont identiques et comparables.


Stéphane Chazelas a noté un cas dans les commentaires où ~ et $HOME donnent des valeurs différentes: si vous unset HOME , alors lorsque vous utilisez ~ Bash appellera getpwuid pour lire une valeur de la database des passwords. Ce cas est exclu par votre condition de n'avoir aucune configuration changeant $HOME , mais je le mentionnerai ici pour être complet.