Entspricht ~ immer $ HOME


40

Ich weiß, dass dies wahrscheinlich schon einmal gefragt wurde, aber ich konnte es bei Google nicht finden.

Gegeben

  • Linux Kernel
  • Keine Konfigurationen, die $ HOME ändern
  • Bash

Wird ~ == $HOMEwahr sein?


3
Ich glaube schon, aber das ist kein Linux-spezifisches Problem. Ich glaube eher, dass ~dies $HOMEin jeder POSIX-Umgebung gleichwertig ist . aber ich könnte mich irren.
HalosGhost

4
Trotz der Antworten unten ... nicht immer. Vergleichen echo "~"und echo "$HOME".
Sparhawk

@Sparhawk Warte, also ist 1 + 1 nicht 2? Es ist eine Verschwörung! Die Regierung versteckt etwas vor uns! : P
Türknauf

1
@Sparhawk, du wirst bemerken, dass das OP entweder das ~oder nicht zitiert hat $HOME. : P
HalosGhost

2
@ HalosGhost Ah, guter Punkt. (Außerdem habe ich später bemerkt, dass Michael Homers Antwort "ein einziges nicht zitiertes ~" nennt .) Jedenfalls etwas, das der Gelegenheitsleser wie ich im Hinterkopf behalten sollte.
Sparhawk

Antworten:


46

Es ist wichtig zu verstehen, dass die ~Erweiterung ein Merkmal der Shell (einiger Shells) ist. Sie ist kein magisches Zeichen, sondern bedeutet, dass Ihr Home-Verzeichnis dort ist, wo es verwendet wird.

Es wird erweitert (durch die Shell, die eine Anwendung zum Interpretieren von Befehlszeilen ist), wie $vares unter bestimmten Bedingungen auf seinen Wert erweitert wird, wenn es in einer Shell-Befehlszeile verwendet wird, bevor der Befehl ausgeführt wird.

Dieses Feature erschien zum ersten Mal in der C-Shell in den späten 1970er Jahren (die Bourne-Shell hatte es nicht, und ihr Vorgänger die Thompson-Shell) 80er Jahre). Es wurde schließlich von POSIX standardisiert und ist jetzt in den meisten Shells verfügbar, einschließlich solcher, die nicht zu POSIX gehören fish.

Da es in Shells so weit verbreitet ist, wird es von einigen Nicht-Shell-Anwendungen auch als Basisverzeichnis erkannt. Das ist bei vielen Anwendungen in ihren Konfigurationsdateien oder ihre eigenen Kommandozeile ( mutt, slrn, vim...).

bashspeziell (die die Hülle des GNU - Projektes ist und weit verbreitet in vielen Linux-basierten Betriebssystemen verwendet wird ), wenn aufgerufen , wie sh, vor allem die folgenden POSIX Regeln über ~Expansion, und in Bereichen , die nicht von POSIX angegeben, verhält sich meist wie der Korn - Shell (von was es ist ein Teil Klon).

Während $vardie Erweiterung an den meisten Stellen (mit Ausnahme von einfachen Anführungszeichen) vorgenommen wird, wird die ~Erweiterung nachträglich nur unter bestimmten Bedingungen durchgeführt.

Es wird erweitert, wenn in Listenkontexten, in Kontexten, in denen eine Zeichenfolge erwartet wird, ein eigenes Argument angegeben wird.

Hier sind einige Beispiele, in denen es erweitert wurde bash:

  • cmd arg ~ other arg
  • var=~
  • var=x:~:x(benötigt von POSIX, verwendet für Variablen wie PATH, MANPATH...)
  • for i in ~
  • [[ ~ = text ]]
  • [[ text = ~ ]](Die Erweiterung ~, in AT & T als Muster verwendet zu werden, kshaber nicht bashseit 4.0).
  • case ~ in ~) ...
  • ${var#~} (wenn auch nicht in anderen Schalen)
  • cmd foo=~(allerdings nicht, wenn es als aufgerufen shwird und nur, wenn das, was links von der =steht, wie ein nicht zitierter bashVariablenname geformt ist. )
  • cmd ~/x (wird natürlich von POSIX benötigt)
  • cmd ~:x(aber nicht x:~:xoder x-~-x)
  • a[~]=foo; echo "${a[~]} $((a[~]))" (nicht in einigen anderen Schalen)

Hier sind einige Beispiele, in denen es nicht erweitert wird:

  • echo "~" '~'
  • echo ~@ ~~(Beachten Sie auch, dass ~udies zum Home-Verzeichnis des Benutzers erweitert werden soll u).
  • echo @~
  • (( HOME == ~ )), $(( var + ~ ))
  • mit extglob: case $var in @(~|other))...(obwohl case $var in ~|other)ist OK).
  • ./configure --prefix=~(da --prefixkein gültiger Variablenname ist)
  • cmd "foo"=~(in bash, wegen der Anführungszeichen).
  • wenn aufgerufen , wie sh: export "foo"=~, env JAVA_HOME=~ cmd...

Zu was es erweitert wird: ~alleine wird zum Inhalt der HOMEVariablen oder, wenn es nicht festgelegt ist, zum Ausgangsverzeichnis des aktuellen Benutzers in der Kontodatenbank erweitert (als Erweiterung, da POSIX dieses Verhalten undefiniert lässt).

Es ist zu beachten, dass in ksh88 und bashVersionen vor 4.0 die Tilde-Erweiterung in Listenkontexten globbing (Dateinamengenerierung) unterzogen wurde:

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

Das sollte im Normalfall kein Problem sein.

Beachten Sie, dass aufgrund der Erweiterung dieselbe Warnung gilt wie für andere Erweiterungsarten.

cd ~

Funktioniert nicht, wenn es $HOMEmit Komponenten beginnt -oder diese enthält ... Also, obwohl es sehr unwahrscheinlich ist, jemals einen Unterschied zu machen, sollte man genau genommen schreiben:

cd -P -- ~

Oder auch:

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

(zur Deckung von Werten $HOMEwie -, +2...) oder einfach:

cd

(wie cdbringt Sie in Ihr Home-Verzeichnis ohne Argumente)

Andere Shells haben fortgeschrittenere ~Erweiterungen. Zum Beispiel zshhaben wir in:

  • ~4, ~-, ~-2(Mit Abschluss) verwendet , um die Verzeichnisse in Ihrem Verzeichnis - Stack (die Orte , die Sie haben zu erweitern , cdum vor).
  • dynamische benannte Verzeichnisse . Sie können Ihren eigenen Mechanismus definieren, um zu entscheiden, wie ~somethingerweitert wird.

25

In jeder Version von Bash auf jedem System, ja . ~als eigenständiger Begriff wird definiert, um zu erweitern:

Der Wert von $ HOME

es wird also immer dasselbe sein, wie $HOMEes für die aktuelle Shell ist. Es gibt mehrere andere Tilde-Erweiterungen, z. B. ~userfür userdas Basisverzeichnis ~von , aber eine einzelne Erweiterung ohne Anführungszeichen wird immer auf erweitert "$HOME".

Beachten Sie, dass das Verhalten von ~und $HOMEin einigen Fällen unterschiedlich sein kann: Insbesondere, wenn $HOMELeerzeichen (oder andere IFS- Zeichen) enthalten sind, wird $HOME(ohne Anführungszeichen) auf mehrere Wörter erweitert, wobei ~es sich immer um ein einzelnes Wort handelt. ~expandiert gleichwertig zu "$HOME"(zitiert).

In Bezug auf Ihre spezifische Frage:

[[ $HOME == ~ ]]

ist immer wahr, weil [[ die Wortteilung unterdrückt . [[ ~ == $HOME ]kann nicht sein, wenn HOMEes Mustervergleichszeichen enthält , aber [[ ~ == "$HOME" ]](dh in Anführungszeichen gesetzt "$HOME") ist immer wahr. Die Verwendung in einzelnen Klammern kann ein Syntaxfehler für Werte sein, HOMEdie Leerzeichen oder Sonderzeichen enthalten. Für jede vernünftige Heimverzeichniskonfiguration ~und "$HOME"sind die gleichen und vergleichen Sie als gleich.


Stéphane Chazelas hat in den Kommentaren einen Fall vermerkt, in dem ~und $HOMEgeben Sie unterschiedliche Werte: Wenn Sie unset HOME, wenn Sie ~Bash verwenden getpwuid, einen Wert aus der Kennwortdatenbank lesen wird. Dieser Fall wird von Ihrer Bedingung ausgeschlossen, dass sich die Konfiguration nicht ändert $HOME. Der Vollständigkeit halber werde ich hier darauf hinweisen.


1
Allerdings /bin/shkönnte nicht sein bash. Ich bin nicht sicher, dass Posix- shSpezifikation erzählt~
Basile Starynkevitch

1
POSIX spezifiziert ~. ~war nicht in der Thomson oder Bourne Shell (die zu ihrer Zeit als verfügbar waren /bin/sh). Es ist nicht in rcoder seine Ableitungen (wo es für etwas anderes verwendet wird)
Stéphane Chazelas

5
In einigen Shells, einschließlich bash, wenn HOMEnicht festgelegt, wird das Basisverzeichnis ~des Benutzers aus der passwd-Datenbank erweitert. Das ist also ein Fall, in dem ~möglicherweise nicht der Wert von erweitert wird $HOME.
Stéphane Chazelas

1
Beachten Sie, dass bashBash4 vor dem Ausführen des Globbing bei der Tilde-Erweiterung (try HOME='/*' bash -c 'echo /*') verwendet wurde. So HOME=/*; [ "$HOME" = ~ ]zurückkehren würde es einen Fehler.
Stéphane Chazelas

4
@ Cuonglm Ich habe den Quellcode überprüft. Es schließlich ruft get_current_user_info , die verwendet getpwuidauf allen Plattformen aber Tandem .
Michael Homer
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.