Comment Linux gère-t-il plusieurs séparateurs de chemin consécutifs (/ home //// nom_utilisateur /// fichier)?

111

Je travaille sur un script python qui transmet les emplacements de fichiers à un sous-processus scp. Tout va bien, mais je suis dans une situation où je pourrais finir par concaténer un chemin avec un nom de fichier tel qu'il y ait un double ' /dans le chemin. Je sais que bash se moque de la présence de plusieurs séparateurs de fichiers, mais je me demande comment cela est rectifié. Est-ce que c'est bash qui enlève des extra /ou est-ce que ça n'a pas vraiment d'importance?

Je demande parce que cela me fera économiser plusieurs lignes de code pour vérifier les /s supplémentaires lors de la concaténation. Je sais que ce n'est pas grave, mais je suis également curieux. J'ai un script bash qui a la ligne cd //usr(au lieu de cd /usr), ce qui semble impliquer qu'il pourrait y avoir une signification à utiliser plusieurs /s dans un chemin

Falmarri
la source
7
J'investirais dans les lignes de code supplémentaires ...
Stefan
5
Juste au cas où quelqu'un se soucie, que je suis sûr que personne ne, je ne finis en fait en utilisant le python joinet abspathet ces commandes.
Falmarri

Réponses:

165

Plusieurs barres obliques sont autorisées et équivalent à une seule barre oblique. A partir de la spécification Single Unix (version 3) , définitions de base §3.266 chemin : «Plusieurs barres obliques successives sont considérées comme identiques à une barre oblique."

Il existe une exception: si un nom de chemin commence par exactement deux barres obliques, il peut être traité différemment (ref: définitions de base, §4.11 résolution du nom de chemin ). Linux lui-même ne fait pas cela, bien que certaines applications le fassent, ainsi que d'autres systèmes unix (par exemple, Cygwin).

Une /fin de chemin à la fin d'un chemin oblige celui-ci à se référer à un répertoire. Dans ( POSIX 1003.1-2001 (v3 Single Unix) définitions de base résolution §4.11 de chemin , une fuite /équivaut à une fuite /.. Posix 1003.1-2008 (Single Unix v4) définitions de base §4.12 supprime l'obligation de rendre équivalent à /., pour pour faire face à des répertoires non existants (par exemple, mkdir foo/est tenu de travailler, alors mkdir foo/.ne serait pas - voir la raison du changement).

Pour les programmes agissant sur une entrée de répertoire, s'il foos'agit d'un lien symbolique vers un répertoire, le passage foo/est un moyen de faire agir le programme sur le répertoire au lieu du lien symbolique.

¹ Notez que cela s’applique uniquement à la résolution du chemin, c’est-à-dire lors de l’accès aux fichiers. Les manipulations de nom de fichier peuvent fonctionner différemment. Par exemple basename, dirnameignorez les barres obliques de fin.

Gilles
la source
7
L'équivalent de /.a été supprimé après un processus de discussion ultérieur car il était ambigu. Quoi qu'il en soit +1 car trouver ce genre d'informations est bien difficile.
hakre
17

Le système d'exploitation ne semble pas non plus s'en soucier, après avoir juste essayé un programme C avec un appel système direct à ouvrir avec un // dans le chemin.

Vous pouvez utiliser la fonction de bibliothèque python os.path.normpath pour la normaliser, ce qui vous évite de parcourir la chaîne à la recherche d’extras. D'autres langues ont des fonctions similaires.

http://docs.python.org/library/os.path.html#os.path.normpath

Ivatar
la source
5
Attention au commentaire suivant dans la source de normpath: Normaliser un chemin, par exemple A // B, A /./ B et A / foo /../ B deviennent tous A / B. Il faut comprendre que cela peut changer la signification du chemin s'il contient des liens symboliques!
Bluehorn
8

Sur tous les systèmes Unix que j'ai vus, c'est la même chose qu'un seul /, mais la norme Unix spécifie que

Un chemin qui commence par deux barres obliques successives peut être interprété de manière définie par l'implémentation, bien que plus de deux barres obliques majeures soient traitées comme une seule barre oblique.

il peut donc être traité spécialement, en fonction de votre système. (Certaines versions Unix plus anciennes utilisaient une double interligne /pour l'accès au système de fichiers distant, et certaines le sont peut-être encore.)

Fred Foo
la source
7
Cygwin (bien qu’il ne s’agisse pas d’un véritable UNIX) est traduit //remote/...en accès de système de fichiers distant, probablement par souci de cohérence avec Windows ' \\remote\....
éphémère
2
Je crois (mais je ne peux pas trouver une bonne référence pour le moment sur Google) que les API Windows POSIX compat traiteront également de //remote/...la même manière que le \\remote\...format de chemin UNC .
Stephen P
1
Je pense me souvenir que les chemins d'accès portables de Boost.Filesystem traitent //de manière spéciale, en ce sens qu'ils peuvent tester l' absolut false, conformément à la spécification Unix / POSIX.
7

Utilisez-le os.path.joinen Python et vous n'aurez pas plusieurs barres obliques. Construire vous-même les noms de fichiers en concaténant des chaînes est considéré comme un style Python médiocre.

Neil Mayhew
la source
Je suis d'accord, mais le nom du fichier fait partie d'une chaîne de commande, et au lieu d'analyser la chaîne de commande à ajouter au nom du fichier (à la fin), j'aimerais simplement l'ajouter.
Falmarri
1
@ Falmarri: Vous ne pouvez pas simplement ajouter un nom de fichier à une chaîne de commande! Une chaîne de commande sera analysée par le shell, de sorte que les caractères spéciaux dans les noms de fichiers doivent être cités. Vous devez donc construire le nom du fichier, puis le citer correctement pour le mettre dans la chaîne de commande.
Gilles
C'est un projet vraiment spécifique que je vais utiliser moi-même. Je n'ai probablement pas été assez clair pour justifier de ne pas être robuste à ce sujet. J'obtiens cette chaîne de chemin de fichier d'une classe qui me donne un chemin de fichier correctement échappé, etc. Et je l'ajoute à un argument en ligne de commande
Falmarri le
1
@ Falmarri: utilisez donc normpath pour nettoyer la valeur de ligne de commande que vous ne contrôlez pas, puis utilisez join pour les associer.
Neil Mayhew
C’est en fait ce que j’ai fini par faire = \ Je ne pouvais pas gérer le cas spécial dans lequel on me donnait /très bien.
Falmarri
3

Il n'y a pas de différence.

Les barres obliques multiples sont ignorées (sans effet), par exemple:

ls -al //usr///////bin/sed
ChristopheD
la source
7
Il peut y avoir si c'est exactement deux et au début; Un chemin qui commence par deux barres obliques successives peut être interprété de manière définie . En pratique, je pense que c'est vrai et qu'ils sont simplement ignorés
Michael Mrozek
Merci Chris, j'apprécie la clarification! (malheureusement, la connexion OpenID ne fonctionne pas pour moi ou je vous voterais)
@Rob Vous n'êtes pas enregistré, mais êtes toujours connecté (votre cookie vous suit). Vous devriez pouvoir vous inscrire maintenant pour connecter un OpenID à votre compte, mais vous devriez pouvoir voter de toute façon
Michael Mrozek
Merci Michael mais "tu dois être connecté ou t'inscrire pour voter". Lorsque vous utilisez uniquement une adresse électronique et un nom, vous ne disposez pas de tous les privilèges. Et comme OpenID arrive à expiration et que je n'ai pas envie de créer un autre compte, je n'ai pas de chance. C'est ma faute d'être paresseux, je suppose, mais j'apprécie l'aide.
0

Bien sûr, vous pouvez normaliser un chemin avec plusieurs / (barres obliques) possibles en le passant tr -s

NORMALIZED=$(echo "$UNHYGIENIC" | tr -s / /)

... et ensuite utiliser $NORMALIZED

Cependant, cela devrait être nécessaire. Pour autant que je sache, tout noyau UNIX proprement dit devrait ignorer les séparateurs de chemins concurrents - ou les traiter de manière conceptuelle comme ... /./...

Jim Dennis
la source
"devrait" -> "ne devrait pas".