La tilde, `~` è considerata un percorso relativo?


35

Sto cercando di estrarre la diversa parte del programma di installazione della libreria cuda di Nvidia. Sto usando il seguente comando:

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

E ricevo il seguente messaggio:

ERROR: extract: path must be absolute.

E quando digito il comando con l'indirizzo letterale di casa mia funziona perfettamente.

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

Sono confuso non dovrebbe essere ~ uguale a / home / like-open / XXX / username?

Provato:

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

e funziona, ma non so perché non lo consenta ~


2
Correlati: "Un" prefisso tilde "è costituito da un carattere <tilde> non
citato

Risposte:


47

Bash espande un ~ solo se è l'inizio di una parola. Puoi vederlo tra i seguenti comandi:

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

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

Bash cerca ~personaggi autonomi e ~/questa sostituzione. Nessuna altra combinazione o versione citata funzionerà.

$HOMEfunziona perché le sostituzioni variabili sono più robuste ( $è un carattere speciale mentre lo ~è molto meno):

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

Mentre stiamo parlando ~, in realtà ha un'altra coppia di altri usi di sostituzione:

  • ~+la directory di lavoro corrente (leggi da $PWD)
  • ~-la directory di lavoro precedente (leggi da $OLDPWD)

Come per la pianura ~, questi possono avere percorsi aggiuntivi fissati alla fine e, di nuovo, questi devono essere il prefisso di una parola o Bash li ignorerà.

Puoi leggere di più al riguardo in man bash | less -p ' Tilde'


2
Vale la pena notare che zsh anche (o meglio può essere configurato per) espandersi anche ~dopo =. Tra gli altri comodi miglioramenti ha superato Bash.
Jan Hudec,

@JanHudec No - è più complicato; Non si tratta di espandersi dopo =; si tratta di espandere all'inizio del lato destro di un'assegnazione variabile. Questo rende il nostro caso un po 'più confuso se guardiamo da vicino - vedi la mia risposta. E zshnon è diverso da bashquesto; La descrizione di 'zsh' è un po 'enigmatica: info --subnodes zsh | less +/'14.7.4 Notes'(mancano le pagine man di zsh)
Volker Siegel,

1
@VolkerSiegel: zshè molto configurabile. Nei miei echo -extract=~/testrisultati zsh in -extract=/home/user/test. È abilitato dalle MAGIC_EQUAL_SUBSTopzioni. In una nota a margine, ho tutte le pagine man di zsh bene.
Jan Hudec,

@JanHudec Non c'è dubbio che zshsia configurabile - e altri miglioramenti; Mi sarei aspettato che MAGIC_EQUAL_SUBST (coperto in 14.7.4) non fosse impostato di default e fosse usato raramente; Ora, ovviamente, è più rilevante se lo hai abilitato in generale. Dopo che avrò la mia sezione di esempio in buone condizioni, sarebbe una bella aggiunta ...
Volker Siegel,

@JanHudec Per quanto riguarda le pagine man di zsh, mancavano da un po 'di tempo dai pacchetti Ubuntu, grazie per il suggerimento, non sapevo che fosse stato corretto; Guardando il bug, è stato risolto in modo utopico, ma non affidabile - questo lo spiega !. ( launchpad: mancano tutte le manpage di zsh e i file di aiuto in linea e AU: man di zsh mancante ... )
Volker Siegel,

19

Sto solo aggiustandolo

Questo comando mostra un messaggio di errore "ERRORE: extract: il percorso deve essere assoluto":

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

L'errore non è utile: il programma era già troppo confuso.
Sai già che l'errore proviene da ~, come funziona $HOMEinvece.

Il problema: ~viene sostituito solo all'inizio di una parola.

Ad esempio, questo funziona con la tilde:

echo -extract ~/Downloads

Se hai bisogno dell'opzione sintassi con =, usare $ HOME invece di ~è la soluzione più pulita;

echo -extract=$HOME/Downloads

La pratica

Cosa dovresti sapere:

Ci sono casi speciali in cui ~get viene espanso quando non all'inizio di una parola: come parte di un'assegnazione variabile, subito dopo il =. Il che è fonte di confusione qui, ovviamente.

L'altro importante caso speciale lo usa per variabili come PATH. Nelle assegnazioni variabili, ~viene anche espanso dopo :, come dopo il primo =.

$ 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

Il significato della tilde

In una conchiglia, ~la tilde, non è davvero un percorso. Viene sostituito solo da un percorso $HOME, alcune volte.

È qualcosa come una scorciatoia, o abbreviazione, fornita dalla shell.
Non può essere usato come un percorso in generale, la shell lo "espande" in un percorso solo in luoghi molto speciali.
E anche se è espanso, può essere qualcosa di diverso dalla home directory.

  • Viene espanso solo all'inizio di una parola o in un'assegnazione variabile dopo un :o=
  • Viene espanso solo se non è racchiuso tra virgolette
  • Viene espanso solo $HOMEse non ci sono altri caratteri nella parola prima di a/

Il problema nella riga di comando

Secondo questo, il problema nel tuo comando è che la tilde dentro

-extract=~/Downloads/nvidia_installers

non è espanso, perché non è uno dei casi elencati. È tutto.

La soluzione potrebbe essere quella di rendere la tilde il primo carattere non citato di una parola, senza nessun altro carattere prima del successivo /- questo è proprio quello che ottieni quando usi un'opzione con uno spazio prima dell'argomento dell'opzione:

-extract ~/Downloads/nvidia_installers

Un'altra soluzione sarebbe quella di utilizzare $HOMEinvece. In una sceneggiatura, questa è generalmente la scelta migliore.

-extract=$HOME/Downloads/nvidia_installers

Il messaggio di errore

Ma come funziona il messaggio di errore
"ERROR: extract: path must be absolute."?
inserirsi in tutto questo?

Sappiamo che la tilde non si è espansa. Ciò significa che il programma ha ottenuto il testo dell'argomento incluso il ~, ma senza /home/auseril percorso. Quel percorso è ~/Downloads/nvidia_installers- ma ora non c'è shell, quindi la tilde non ha un significato speciale. È solo un normale nome di directory. E come ogni altro percorso della forma foo/bar/baz, è un percorso relativo

Altri usi

Se ci sono caratteri dopo il ~, come in ~alice- con tutte le altre regole sopra applicate - e c'è un nome utente alice, che viene invece espanso nella directory home di alice, diciamo home/alice.
Inoltre, se lo sei bob, ~si espanderà /home/bobe ~bobsi espanderà allo stesso.

La variante ~+viene espansa nella directory corrente,$PWD

Per fare riferimento alla directory precedente, dove si trovava prima dell'ultima cd, è possibile utilizzare ~-, che è espanso in $OLDPWD.

Se usi pushde popd, invece di cd, saprai già che è possibile accedere allo stack di directory come ~-2.

Dettagli

Tutti i casi in cui ~è espanso in un percorso sono gestiti dalla shell . Per altri programmi, ~è solo un normale carattere di nome file.

Per la definizione esatta all'interno della shell, ecco la sezione pertinente della Nota in cui la sostituzione di è solo un caso speciale di molti casi: "Se questo nome di accesso è la stringa nulla, la tilde viene sostituita con il valore del parametro della shell HOME. " :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.

3

~non è un percorso in sé. È un personaggio che riceve un trattamento speciale dalla shell dove ~o ~/significa "sostituisci con il percorso della directory home dell'utente corrente". ~usernamesignifica "sostituisci con il percorso della home directory del nome utente".

Poiché non è un percorso, viene riconosciuto solo in alcuni punti del comando (come primo carattere di un nuovo token di divisione dello spazio).

Se espanso, è stato sostituito con un percorso assoluto.

L'uso di $HOMEfunziona perché HOME è solo una variabile impostata dalla shell e segue le normali regole della shell per la sostituzione delle variabili (accade prima che l'input venga suddiviso sugli spazi ed eseguito).


1

Hai ragione. ~ / Download è uguale a / home / nome utente / Download.

Alcuni installatori ed estrattori sono solo molto esigenti su dove deve mettere le cose. Penso che potrebbe essere perché registra i percorsi dei file e i registri non accetteranno ~ in un percorso accettato.

Mi sono appena abituato a digitare / home / username invece. :)

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.