Le tilde `` `est-il considéré comme un chemin relatif?

35

J'essaie d'extraire les différentes parties du programme d'installation de la bibliothèque Nvidia cuda. J'utilise la commande suivante:

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

Et je reçois le message suivant:

ERROR: extract: path must be absolute.

Et lorsque je tape la commande avec l'adresse littérale de mon domicile, cela fonctionne parfaitement.

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

Je suis confus ne devrait pas être ~ identique à / home / likewise-open / XXX / nom d'utilisateur?

Testé:

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

et ça marche, mais je ne sais pas pourquoi ça ne permet pas ~

Regan
la source
2
Connexes: "Un" préfixe tilde "se compose d'un caractère <tilde> non
guidé

Réponses:

47

Bash ne développe un ~ que s'il s'agit du début d'un mot. Vous pouvez le voir entre les commandes suivantes:

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

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

Bash recherche les ~caractères autonomes et ~/cette substitution. Aucune autre combinaison ou version citée ne fonctionnera.

$HOMEfonctionne parce que les substitutions de variables sont plus robustes ( $c’est un caractère spécial alors que ~c’est beaucoup moins):

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

Pendant que nous parlons ~, il a en fait encore deux autres utilisations de substitution:

  • ~+le répertoire de travail actuel (extrait de $PWD)
  • ~-le répertoire de travail précédent (à lire $OLDPWD)

Comme avec plain ~, ceux-ci peuvent avoir des chemins supplémentaires ajoutés à la fin, et encore une fois, ceux-ci doivent être le préfixe d'un mot ou Bash les ignorera.

Vous pouvez en savoir plus à ce sujet dans man bash | less -p ' Tilde'

Oli
la source
2
Il est intéressant de noter que zsh ne (ou plutôt peut être configuré pour) , vous agrandissez ~après =aussi. Parmi d'autres améliorations pratiques, il a plus de bash.
Jan Hudec
@ JanHudec Non - c'est plus compliqué; Il ne s'agit pas d'expansion après =; il s’agit d’agrandir au début du côté droit d’une affectation de variable. Cela rend notre cas un peu plus confus quand on regarde de près - voir ma réponse. Et zshn'est pas différent de bashcela; La description de 'zsh' est un peu cryptique: info --subnodes zsh | less +/'14.7.4 Notes'(les pages de manuel de zsh sont manquantes)
Volker Siegel le
1
@VolkerSiegel: zshest très configurable. Dans mes echo -extract=~/testrésultats zsh dans -extract=/home/user/test. Il est activé par les MAGIC_EQUAL_SUBSToptions. En passant, toutes les pages de manuel zsh sont correctes.
Jan Hudec
@JanHudec Aucun doute sur le fait d' zshêtre configurable - et d'autres améliorations; Je me serais attendu à ce que MAGIC_EQUAL_SUBST (couvert en 14.7.4) soit non défini par défaut et rarement utilisé; Maintenant, c'est évidemment plus pertinent si vous l'avez activé en général. Après avoir obtenu un bon exemple de ma section, cela ferait une belle addition ...
Volker Siegel
@JanHudec En ce qui concerne les pages de manuel zsh, elles étaient absentes des paquets Ubuntu pendant un certain temps, merci pour l'allusion, ne savaient pas que cela avait été corrigé; En regardant le bogue, il est réglé pour utopique, mais pas fidèle - cela explique cela!. ( tableau de bord: toutes les pages de manuel zsh et les fichiers d'aide en ligne sont manquants et AU: homme zsh manquant ... )
Volker Siegel
19

Il suffit de le réparer

Cette commande affiche un message d'erreur "ERREUR: extraire: le chemin doit être absolu":

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

L'erreur n'est pas utile - le programme était déjà trop confus.
Vous savez déjà que l'erreur provient de la ~, car cela fonctionne à la $HOMEplace.

Le problème: est ~seulement remplacé au début d'un mot.

Par exemple, cela fonctionne avec le tilde:

echo -extract ~/Downloads

Si vous avez besoin de la syntaxe d'option avec =, utiliser $ HOME à la place de ~est la solution la plus propre.

echo -extract=$HOME/Downloads

La pratique

Ce que vous devriez savoir:

Il y a des cas spéciaux où ~get est développé quand il ne se trouve pas au début d'un mot: dans le cadre d'une affectation de variable, juste après le =. Ce qui est déroutant ici, bien sûr.

L’autre cas particulier important est l’utilisation avec des variables comme PATH. Dans les affectations de variables, ~est également développé après :, comme après le premier =.

$ 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

Le sens du tilde

Dans un shell, ~le tilde n'est pas vraiment un chemin. Il est seulement remplacé par un chemin $HOME, quelques fois.

C'est quelque chose comme un raccourci, ou une abréviation, fourni par le shell.
Il ne peut pas être utilisé comme un chemin en général, le shell le "développe" en chemin seulement dans des endroits très spéciaux.
Et même s'il est étendu, cela peut être autre chose que le répertoire personnel.

  • Il est développé uniquement au début d'un mot ou dans une affectation de variable après un :ou=
  • Il est seulement étendu si c'est pas entre guillemets
  • Il est étendu uniquement $HOMEs’il n’ya plus de caractères dans le mot avant une/

Le problème en ligne de commande

Selon cela, le problème dans votre commande est que le tilde dans

-extract=~/Downloads/nvidia_installers

n'est pas développé, car ce n'est pas l'un des cas énumérés. C'est tout.

La solution pourrait consister à faire du tilde le premier caractère non cité entre mots, sans autre caractère avant le suivant /- c'est exactement ce que vous obtenez lorsque vous utilisez une option avec un espace avant l'argument d'option:

-extract ~/Downloads/nvidia_installers

Une autre solution serait d'utiliser à la $HOMEplace. Dans un script, c'est généralement le meilleur choix.

-extract=$HOME/Downloads/nvidia_installers

Le message d'erreur

Mais comment fonctionne le message d'erreur
"ERROR: extract: path must be absolute."?
s'intégrer dans tout cela?

Nous savons que le tilde n'a pas été élargi. Cela signifie que le programme a obtenu le texte de l’argument incluant le ~, mais sans le /home/ausercomme chemin. Ce chemin est ~/Downloads/nvidia_installers- mais maintenant il n'y a pas de shell, le tilde n'a donc aucune signification particulière. C'est juste un nom de répertoire normal. Et comme tout autre chemin de la forme foo/bar/baz, c'est un chemin relatif

Autres utilisations

S'il y a des caractères après le ~, comme dans ~alice- avec toutes les autres règles ci-dessus qui s'appliquent - et s'il y a un nom d'utilisateur alice, celui-ci est étendu au répertoire de base de alice, disons home/alice.
En outre, si vous êtes bob, ~élargirait /home/bobet ~bobétendrait au même.

La variante ~+est étendue au répertoire en cours,$PWD

Pour faire référence au répertoire précédent, où vous étiez avant le dernier cd, vous pouvez utiliser ~-, qui est développé $OLDPWD.

Si vous utilisez pushdet popd, au lieu de cd, vous saurez déjà que la pile de répertoires est accessible comme ~-2.

Détails

Tous les cas où ~est étendu à un chemin sont manipulés par le shell . Pour d'autres programmes,~ c'est juste un caractère de nom de fichier normal.

Pour la définition exacte à l’intérieur du shell, voici la section pertinente de Remarquez que le remplacement par n'est qu'un cas particulier parmi de nombreux cas: "Si ce nom de connexion est la chaîne vide, le tilde est remplacé par la valeur du paramètre de 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.
Volker Siegel
la source
3

~n'est pas un chemin en soi. C'est un personnage qui reçoit un traitement spécial de la part du shell, qui signifie ~ou ~/"remplace par le chemin du répertoire de base de l'utilisateur actuel".~usernamesignifie "remplacer par le chemin du répertoire personnel du nom d'utilisateur".

Comme il ne s'agit pas d'un chemin, il est uniquement reconnu à certains endroits de la commande (en tant que premier caractère d'un nouveau jeton de division d'espace).

Lorsqu'il est développé, il est remplacé par un chemin absolu.

Utiliser $HOMEfonctionne parce que HOME est juste une variable définie par le shell et suit les règles normales du shell pour le remplacement des variables (cela se produit avant que l’entrée ne soit fractionnée sur des espaces et exécutée).

Daenyth
la source
1

Vous avez raison. le ~ / Téléchargements est identique à / home / nom d'utilisateur / Téléchargements.

Certains installateurs et extracteurs sont juste très pointilleux sur l'endroit où il faut mettre les choses. Je pense que c'est peut-être parce qu'il enregistre les chemins de fichiers et que les journaux n'acceptent pas ~ dans un chemin accepté.

Je viens de prendre l'habitude de taper / home / nom d'utilisateur à la place. :)

Dan Johansen
la source