Y a-t-il une différence entre les chemins «fichier» et «./fichier»?

12

Comme le titre l'indique, y a-t-il une différence pour les systèmes de fichiers * NIX? par exemple ls fileetls ./file

Sergey Alaev
la source
1
Vous pourriez demander à unix.stackexchange.com - jusqu'à présent, toutes les réponses contiennent de bonnes informations, mais aucune ne ressemble vraiment à la réponse.
Rob Starling

Réponses:

14

Je ne suis pas fou de l'explication de SmallLoanOf1M. Il est techniquement correct mais répond d'une manière qui ne correspond pas à l'exemple d'utilisation de la question.

Donc, à titre d'exemple, voici une différence importante entre les deux de la question: "fichier" et "./fichier"

Que faire si le fichier est nommé avec un caractère analysé par le shell? Surtout en ce qui concerne les caractères interprétés par la commande que l'on exécute.

Plus précisément, le caractère "tiret": "-". Mais d'autres personnages ont un sens pour le shell.

Exemple. Mon fichier a été nommé "-dingle"

Essayez de répertorier le fichier:

ls -dingle
# ls -dingle
ls: invalid option -- 'e'

Pire encore, que se passe-t-il si le fichier est nommé " -rf rmbomb *"? Maintenant, essayez de le supprimer

rm "-rf rmbomb *"

Je ne vais même pas essayer d'exécuter cet exemple, mais j'espère que vous aurez l'idée.

Alors, comment listez-vous un fichier avec un tiret? Utiliser ./devant.

# ls ./-dingle
./-dingle

Idem pour rm

JDS
la source
C'est une façon valide de traiter certains fichiers avec des noms bizarres, et ma réponse n'a pas considéré les fichiers comme ça. On pourrait également utiliser un littéral à la place dans tous les exemples ci-dessus, sous la forme d'une barre oblique inverse précédant les caractères impairs, y compris les espaces spécifiés ci-dessus. Un exemple en serait le cas: ls \-dingleou ls \-rf\ rmbomb\ \*. Cela peut être un bon moyen de s'assurer que tout ensemble de commandes donné est au moins cohérent, car spécifier ./avant un nom n'échappera pas aux caractères après le ./.
Spooler
2
Il arrive que, puisque les échappements sont échappés par le shell, pas la commande, et que les paramètres soient analysés par la commande, échapper ou citer le - ne fait rien d'utile.
Dewi Morgan
2
Vous donnez l'impression que rm "-rf rmbomb *"cela ferait quelque chose de mal, au lieu de simplement rmimprimer une erreur. C'est seulement dangereux si vous oubliez de citer le nom du fichier, donc le fractionnement de mots se produit. (en particulier dans un script shell où vous exécutez à la rm $fileplace de rm "$file". Mais dans ce cas, le *ne se développera pas, car l'expansion globale ne se produit pas sur le contenu de l'expansion variable. Si vous le souhaitez, vous auriez besoin d'un eval.) Quoi qu'il en soit, si votre script divise les noms de fichiers avant de passer à rm, je créerais un fichier appelé space -rf .ou quelque chose, donc rm ./$iça n'aide pas.
Peter Cordes
1
BTW, le message d'erreur réel est rm: invalid option -- ' ', à partir du moment où il essaie d'interpréter l'espace après -rfcomme un commutateur à un seul caractère, car il fait partie du même argument. (Et oui, j'ai couru cela dans un répertoire vide juste au cas où j'aurais oublié quelque chose et que c'était en fait dangereux: P)
Peter Cordes
2
@PeterCordes: le fractionnement de mots et le globbing se produisent sur les résultats de l'expansion de variable non citée et de la substitution de commande, sauf s'ils sont supprimés par IFS=''et -frespectivement. Un exemple plus rare est celui qui awktraite un opérande (autre qu'un premier opérande qui est le script) ayant la forme foo=barcomme une affectation à exécuter mais ./foo=barcomme un fichier à lire.
dave_thompson_085
7

Oui.

En émettant filesur la ligne de commande, BASH recherchera dans votre variable d'environnement $ PATH un fichier de ce nom. À moins que le fichier ne réside dans un répertoire de votre variable $ PATH, il ne sera pas trouvé.

.signifie le répertoire courant. ./signifie dans le répertoire courant, en termes relatifs. C'est l'équivalent de dire quelque chose comme /home/sheogorath/shivering/isles.imglors de l'appel ./isles.imgen travaillant dans le /home/sheogorath/shivering/répertoire.

En tant que tel, il est couramment utilisé pour exécuter des fichiers dans votre répertoire de travail "sur place".

EDIT: Dans votre exemple, lsest appelé par le shell et trouvé en utilisant la variable path. Son argument sera traité dans votre répertoire de travail, quel qu'il soit. Comme il s'agit de la valeur par défaut pour ls, vous ne verrez aucune différence entre la spécification fileet la spécification explicite ./filecar elles pointent toutes les deux vers votre répertoire actuel.

Toutes les commandes n'acceptent pas les chemins de fichiers dans le répertoire de travail, et certains s'attendent à ce que vous ayez des fichiers d'état dans un répertoire qu'ils ont eux-mêmes prédéfinis via la configuration. Parmi les commandes qui acceptent les fichiers comme arguments, ces commandes sont moins courantes

Spouleur
la source
1
C'est bash, mais je me posais des questions sur la résolution de chemin en général
Sergey Alaev
1
C'est ainsi que fonctionne tout shell que j'ai jamais entendu parler. BASH est simplement le plus couramment utilisé.
Spooler
4
$ PATH n'est pertinent que pour les commandes et n'a rien à voir avec les arguments de nom de fichier qui suivent une commande telle que lsmentionnée dans la question d'origine. C'est plus la différence entre réaffecter un chemin relatif (par rapport au répertoire de travail actuel) Ie ../../dir/filenameet un chemin absolu /path/to/dir/filename
HBruijn
1
+1 pour Sheogorath ... et une bonne réponse.
Corey Ogburn
1
S'ils sont des arguments d'une commande qui tente de trouver des fichiers dans le répertoire de travail par défaut, ils seront les mêmes. Ainsi, car lsils seront toujours le même chemin, l'un spécifié plus explicitement que l'autre. Toutes les commandes ne se comportent pas de cette façon lors du traitement des arguments, mais la plupart le font.
Spooler