Wird die Tilde als relativer Pfad betrachtet?

35

Ich versuche, den anderen Teil des Nvidia cuda-Bibliotheksinstallationsprogramms zu extrahieren. Ich benutze den folgenden Befehl:

mkdir ~/Downloads/nvidia_installers
./cuda_6.5.14_linux_64.run -extract=~/Downloads/nvidia_installers

Und ich bekomme folgende Meldung:

ERROR: extract: path must be absolute.

Und wenn ich den Befehl mit der wörtlichen Adresse meines Hauses eingebe, funktioniert er perfekt.

./cuda_6.5.14_linux_64.run -extract=/home/likewise-open/XXX/username/Downloads/nvidia_installers

Ich bin verwirrt, sollte ~ nicht mit / home / ebenfalls-open / XXX / username identisch sein?

Geprüft:

./cuda_6.5.14_linux_64.run -extract=$HOME/Downloads/nvidia_installers

und es funktioniert, aber ich weiß nicht, warum es nicht erlaubt ~

Regan
quelle
2
Verwandte: "Ein" Tilde-Präfix "besteht aus einem nicht zitierten <Tilde> -Zeichen am Anfang eines Wortes, gefolgt von allen Zeichen vor dem ersten nicht
zitierten

Antworten:

47

Bash erweitert ein ~ nur, wenn es der Anfang eines Wortes ist. Sie können dies zwischen den folgenden Befehlen sehen:

$ echo -extract=~/test
-extract=~/test

oli@bert:~$ echo -extract ~/test
-extract /home/oli/test

Bash sucht nach eigenständigen ~Zeichen und ~/nach dieser Ersetzung. Keine andere Kombination oder zitierte Version wird funktionieren.

$HOMEfunktioniert, weil variable Substitutionen robuster sind (das $ist ein Sonderzeichen, wohingegen ~es sehr viel weniger ist):

$ echo Thisisastring${HOME}awrawr
Thisisastring/home/oliawrawr

Während wir darüber reden ~, hat es tatsächlich noch ein paar andere Substitutionsmöglichkeiten:

  • ~+das aktuelle Arbeitsverzeichnis (gelesen von $PWD)
  • ~-das vorherige Arbeitsverzeichnis (gelesen von $OLDPWD)

Wie bei plain ~können diese am Ende zusätzliche Pfade haben, und diese müssen wiederum das Präfix eines Wortes sein, oder Bash ignoriert sie.

Mehr dazu lesen Sie in man bash | less -p ' Tilde'

Oli
quelle
2
Es ist erwähnenswert, dass zsh auch~ nachher expandiert (oder vielmehr konfiguriert werden kann) =. Unter anderen praktischen Verbesserungen hat es über Bash.
Jan Hudec
@ JanHudec Nein - es ist komplizierter; Es geht nicht darum, nachher zu expandieren =; es geht darum, am anfang der rechten seite eine variable zuordnung zu erweitern. Das macht unseren Fall bei näherer Betrachtung etwas verwirrender - siehe meine Antwort. Und unterscheidet zshsich darin nicht bash; Die Beschreibung für 'zsh' ist ein wenig kryptisch: info --subnodes zsh | less +/'14.7.4 Notes'(zsh Manpages fehlen)
Volker Siegel
1
@ VolkerSiegel: zshist sehr konfigurierbar. In meinem zsh echo -extract=~/testergibt sich -extract=/home/user/test. Es wird durch MAGIC_EQUAL_SUBSTOptionen aktiviert . Als Randnotiz habe ich alle zsh-Manpages ganz gut.
Jan Hudec
@JanHudec Ohne Zweifel zshkonfigurierbar - und andere Verbesserungen; Ich hätte erwartet, dass MAGIC_EQUAL_SUBST (in 14.7.4 behandelt) standardmäßig deaktiviert und selten verwendet wird. Jetzt ist es offensichtlich relevanter, wenn Sie es allgemein aktiviert haben. Nachdem ich meine Beispielsektion in einen guten Zustand gebracht habe, wäre das eine schöne Ergänzung ...
Volker Siegel
@JanHudec In Bezug auf die zsh-Manpages fehlten sie für eine Weile in den Ubuntu-Paketen, danke für den Hinweis, wussten nicht, dass das behoben wurde; Wenn man sich den Fehler ansieht, ist er als utopisch, aber nicht als vertrauenswürdig eingestuft - das erklärt es !. ( Launchpad: Alle zsh-Hilfeseiten und Inline-Hilfedateien fehlen und AU: zsh-Man fehlt ... )
Volker Siegel
19

Ich repariere es einfach

Dieser Befehl zeigt eine Fehlermeldung "ERROR: extract: path must be absolute" an:

./cuda_6.5.14_linux_64.run -extract=~/Downloads/nvidia_installers

Der Fehler ist nicht hilfreich - das Programm war bereits zu verwirrt.
Sie wissen bereits, dass der Fehler vom liegt ~, da er $HOMEstattdessen mit funktioniert .

Das Problem: ~Wird nur am Anfang eines Wortes ersetzt.

Dies funktioniert zum Beispiel mit der Tilde:

echo -extract ~/Downloads

Wenn Sie die Optionssyntax mit benötigen =, ist die Verwendung von $ HOME anstelle von ~die sauberste Lösung.

echo -extract=$HOME/Downloads

Die Übung

Was du wissen solltest:

Es gibt spezielle Fälle, in ~denen nicht am Anfang eines Wortes erweitert wird: als Teil einer variablen Zuweisung, direkt nach dem =. Was hier natürlich verwirrend ist.

Der andere wichtige Spezialfall ist die Verwendung mit Variablen wie PATH. Bei variablen Zuweisungen ~wird auch nach :, wie nach dem ersten, erweitert =.

$ dir=~ sh -c 'echo D2: $dir'
D2: /home/user
$ sh -c 'echo D2: $dir' dir=~
D2: 
$ echo Dir: $dir
Dir:
$ dir=~; sh -c 'echo D2: $dir'
D2: 
$ echo Dir: $dir
Dir: /home/user
$ sh -c 'echo D2: $dir'; d3=~
D2: 
$ echo d3: $d3
d3: /home/user

Die Bedeutung der Tilde

In einer Shell ist ~die Tilde nicht wirklich ein Pfad. Es wird nur gelegentlich durch einen Pfad ersetzt $HOME.

Es ist so etwas wie eine Abkürzung, die von der Shell bereitgestellt wird.
Es kann im Allgemeinen nicht wie ein Pfad verwendet werden, die Shell "erweitert" es nur an ganz bestimmten Stellen zu einem Pfad.
Und selbst wenn es erweitert ist, kann es sich um etwas anderes als das Basisverzeichnis handeln.

  • Es wird nur am Anfang eines Wortes oder in einer variablen Zuordnung nach einem :oder erweitert=
  • Es wird nur erweitert, wenn es nicht in Anführungszeichen steht
  • Es wird nur erweitert, $HOMEwenn das Wort vor a keine weiteren Zeichen enthält/

Das Problem in der Kommandozeile

Demnach besteht das Problem in Ihrem Befehl darin, dass die Tilde in

-extract=~/Downloads/nvidia_installers

wird nicht erweitert, da es sich nicht um einen der aufgelisteten Fälle handelt. Das ist alles.

Die Lösung könnte darin bestehen, die Tilde zum ersten nicht in Anführungszeichen gesetzten Zeichen eines Wortes zu machen, ohne dass ein anderes Zeichen vor dem nächsten steht /- genau das erhalten Sie, wenn Sie eine Option mit einem Leerzeichen vor dem Optionsargument verwenden:

-extract ~/Downloads/nvidia_installers

Eine andere Lösung wäre, $HOMEstattdessen zu verwenden . In einem Skript ist das normalerweise die bessere Wahl.

-extract=$HOME/Downloads/nvidia_installers

Die Fehlermeldung

Aber wie sieht die Fehlermeldung aus
"ERROR: extract: path must be absolute."?
in all das passen?

Wir wissen, dass die Tilde nicht erweitert wurde. Das heißt, das Programm hat den Argumenttext einschließlich ~, aber ohne /home/auserals Pfad erhalten. Dieser Pfad ist ~/Downloads/nvidia_installers- aber jetzt gibt es keine Muschel, daher hat die Tilde keine besondere Bedeutung. Es ist nur ein normaler Verzeichnisname. Und wie jeder andere Pfad der Form foo/bar/bazist es ein relativer Pfad

Andere Verwendungen

Wenn es Zeichen nach dem sind ~, wie in ~alice- mit allen anderen Regeln über die Anwendung - und es gibt einen Benutzernamen alice, die auf dem Home - Verzeichnis erweitert wird alicestattdessen sagen home/alice.
Wenn Sie dies tun bob, ~erweitern Sie auf /home/bobund ~boberweitern Sie auf dasselbe.

Die Variante ~+wird zum aktuellen Verzeichnis erweitert.$PWD

Um auf das vorherige Verzeichnis zu verweisen, in dem Sie sich vor dem letzten befanden cd, können Sie das Verzeichnis verwenden ~-, auf das erweitert wird $OLDPWD.

Wenn Sie pushdund popdanstelle von verwenden cd, wissen Sie bereits, dass auf den Verzeichnisstapel wie folgt zugegriffen werden kann ~-2.

Einzelheiten

Alle Fälle, in denen ~ein Pfad erweitert wird, werden von der Shell behandelt . Bei anderen Programmen ~ist dies nur ein normaler Dateiname.

Für die genaue Definition innerhalb der Shell ist hier der relevante Abschnitt von Hinweis, wie das Ersetzen durch nur ein Sonderfall von vielen Fällen ist: "Wenn dieser Anmeldename die Nullzeichenfolge ist, wird die Tilde durch den Wert des Shellparameters HOME ersetzt. " :man bash
~$HOME

Tilde Expansion
    If a word begins with an unquoted tilde character (`~'), all of the charac‐
    ters  preceding the first unquoted slash (or all characters, if there is no
    unquoted slash) are considered a tilde-prefix.  If none of  the  characters
    in  the tilde-prefix are quoted, the characters in the tilde-prefix follow‐
    ing the tilde are treated as a possible login name.  If this login name  is
    the  null string, the tilde is replaced with the value of the shell parame‐
    ter HOME.  If HOME is unset, the home directory of the user  executing  the
    shell is substituted instead.  Otherwise, the tilde-prefix is replaced with
    the home directory associated with the specified login name.

    If the tilde-prefix is a `~+', the value of the shell variable PWD replaces
    the  tilde-prefix.   If  the tilde-prefix is a `~-', the value of the shell
    variable OLDPWD, if it is set, is substituted.  If the characters following
    the tilde in the tilde-prefix consist of a number N, optionally prefixed by
    a `+' or a `-', the tilde-prefix is replaced with the corresponding element
    from  the  directory  stack,  as  it would be displayed by the dirs builtin
    invoked with the tilde-prefix as an argument.  If the characters  following
    the  tilde in the tilde-prefix consist of a number without a leading `+' or
    `-', `+' is assumed.

    If the login name is invalid, or the tilde expansion  fails,  the  word  is
    unchanged.

    Each variable assignment is checked for unquoted tilde-prefixes immediately
    following a : or the first =.  In these cases, tilde expansion is also per‐
    formed.   Consequently, one may use filenames with tildes in assignments to
    PATH, MAILPATH, and CDPATH, and the shell assigns the expanded value.
Volker Siegel
quelle
3

~ist kein Weg an sich. Es ist ein Charakter, der eine spezielle Behandlung von der Shell erhält, bei der ~oder ~/bedeutet "Ersetzen durch den Heimatverzeichnispfad des aktuellen Benutzers". ~usernamebedeutet "durch den Heimatverzeichnispfad des Benutzernamens ersetzen".

Da es sich nicht um einen Pfad handelt, wird er nur an bestimmten Stellen im Befehl erkannt (als erstes Zeichen eines neuen Space-Split-Tokens).

Wenn es erweitert wird, wird es durch einen absoluten Pfad ersetzt.

Verwenden von $HOMEWorks, da HOME nur eine von der Shell festgelegte Variable ist und die normalen Shell-Regeln für das Ersetzen von Variablen befolgt (dies geschieht, bevor die Eingabe in Leerzeichen aufgeteilt und ausgeführt wird).

Daenyth
quelle
1

Du hast Recht. Das ~ / Downloads ist dasselbe wie / home / username / Downloads.

Einige Installateure und Extraktoren sind nur sehr wählerisch, wo sie Dinge platzieren müssen. Ich denke, es könnte daran liegen, dass die Dateipfade protokolliert werden und die Protokolle ~ in einem akzeptierten Pfad nicht akzeptieren.

Ich habe mich nur daran gewöhnt, stattdessen / home / username einzugeben. :)

Dan Johansen
quelle