Existe-t-il un moyen conventionnel de combiner des chaînes de chemin de fichier?

34

Dans un exemple:

var assets = "images/"

var sounds = assets+"sounds/"

Est-il plus conventionnel de mettre la barre oblique à l'arrière d'un chemin de fichier?

var assets = "/images"

var sounds = assets+"/sounds"

Y at-il une autre méthode qui est une bonne pratique courante?

iiridescent
la source
Java a les chaînes statiques File.separator et File.pathSeparator qui semblent pertinentes. Ainsi, vous êtes en sécurité sur toutes les plateformes
Evorlor
1
@Evorlor Cependant, vous devez rarement utiliser File.separator, les API Fileet Pathacceptent les deux /et `\`.
Kapex
2
Pourriez-vous indiquer quelle langue vous utilisez, s'il vous plaît? Cela vaut probablement la peine d'ajouter la balise correspondante.
Christopher Creutzig
@ChristopherCreutzig J'utilise Java - bien que je demandais s'il existait des conventions couramment utilisées pour combiner des répertoires de fichiers dans des chaînes. Apparemment, il existe quelques règles généralement acceptées et un peu de bon sens, mais cela varie un peu d’une langue à l’autre.
iiridescent
1
Pour ce que cela vaut, dans le monde Unix (et dans les URL), plusieurs barres obliques situées au milieu d'un chemin sont traitées de la même manière qu'une seule, de sorte que rien de mal ne se produirait si vous vous trompiez davantage. Cela fait partie de la spécification Single Unix; voir cette réponse - unix.stackexchange.com/a/1919/21161
yoniLavi

Réponses:

37

Presque tous les principaux langages de programmation ont une bibliothèque pour gérer les séparateurs de répertoires pour vous. Vous devriez les exploiter. Cela simplifiera votre code et évitera les bugs .

D'après mon expérience, la raison habituelle pour combiner des chaînes de ce type est qu'elles proviennent de sources différentes. Parfois, il s'agit de pièces différentes d'un fichier de configuration. Parfois, c'est une combinaison constante avec un argument de fonction. Dans tous les cas, quand ils proviennent de sources différentes, vous devez considérer plusieurs cas possibles concernant les séparateurs aux extrémités à combiner:

  • Les deux extrémités pourraient avoir un séparateur: "images/"et"/sounds"
  • Un seul a un séparateur: "images"et "/sounds"ou "images/"et"sounds"
  • Ni un séparateur: "images"et"sounds"

Le fait que chaque partie provienne d'une source différente signifie que chaque source peut avoir ses propres idées sur les conventions à suivre, si quelqu'un y réfléchit du tout! Tout ce qui appelle votre code ne devrait pas avoir à s'inquiéter de cela . Votre code doit gérer tous les cas, car quelqu'un violera votre convention . Cela se traduira par une perte de temps pour rechercher la cause d'une erreur et apporter une solution. À plusieurs reprises, un collègue a supposé que les chemins d'accès devaient être formatés dans un fichier de configuration, ce qui signifiait que je devais rechercher le code et déterminer ce à quoi il s'attendait (ou le corriger).

La plupart des langues principales fournissent une méthode pour le faire pour vous, qui gère déjà de nombreux cas:

Il y a une mise en garde avec ceux-ci. Un certain nombre d'entre eux semblent supposer qu'un séparateur de répertoire en tête dans le deuxième argument fait référence à un chemin racine, ce qui signifie que le premier argument doit être entièrement supprimé. Je ne sais pas pourquoi c'est considéré comme utile. pour moi, cela ne fait que poser des problèmes. Je n'ai jamais voulu combiner deux portions de chemin et finir par abandonner la première. Lisez attentivement la documentation pour les cas particuliers et, si nécessaire, écrivez un wrapper qui fait ce que vous voulez avec ceux-ci au lieu de leur traitement spécial.

Cela aide également si vous avez besoin de prendre en charge différents systèmes d'exploitation. Presque partout, ces classes expliquent le choix du bon séparateur. Les bibliothèques disposent généralement d’un moyen de normaliser les chemins pour s’adapter aux conventions du système d’exploitation.

Au cas où votre langage de programmation ne dispose pas d'une bibliothèque facilement disponible, vous devez écrire une méthode qui gère tous ces cas et l'utiliser de manière libérale et entre projets.

Cela tombe dans la catégorie "ne faites pas de suppositions" et "utilisez des outils qui vous aident".

jpmc26
la source
2
Path.Combine de .NET n'est pas cassé. Il suffit de ne pas nourrir les séparateurs. assurez-vous de lire la documentation, si le deuxième argument est un chemin racine, il a un résultat défini. Vous n’aimerez peut-être pas cela, mais cela ne signifie pas qu’il est cassé.
Erno
4
Assurez-vous de lire la documentation pour vous assurer que vous n'essayez pas d'être trop malin. Une fois, j’ai utilisé une bibliothèque qui pouvait être combinée C:\Documents and Settings\Adminavec my folder:document.txtun système * nix pour produire /home/admin/my folder/document.txt- un joli tour, mais dans le monde réel, les heuristiques impliquées introduisaient plus de bugs qu’elles ne corrigeaient.
Mark
1
En outre, pour Java, Paths.get()convertit simplement Stringun Pathobjet unique en objet. Pour rejoindre des chemins, vous utiliseriez Path.resolve()ce qui peut en prendre un autre Pathou un String. Il existe d'autres méthodes dans la Pathclasse qui permettent en outre de joindre des chemins de différentes manières.
Kat
1
Ma mauvaise, il semble que je n'ai pas lu la documentation pour Pathstrès bien.
Kat
1
Sur PowerShell, une alternative à la méthode .NET [System.IO.Path]::Combine("abc", "\def")qui a le comportement décrit, est l'applet de commande Join-Path "abc" "\def"qui donne "abc\def".
Jeppe Stig Nielsen
38

En Java, la réponse serait "ni l'un ni l'autre". La meilleure pratique serait d’assembler des noms de chemins en utilisant la java.io.Fileclasse; par exemple

File assets = new File("images");
File sounds = new File(assets, "sounds");

La Fileclasse prend également en charge les séparateurs de noms de chemins spécifiques à la plate-forme.

Il y a une question distincte de savoir si votre chemin doit commencer par une barre oblique ou non. Mais cela relève plus de l’exactitude que de la meilleure pratique. Un chemin qui commence par un slash signifie autre chose qu'un chemin qui ne le fait pas !!


Il n’existe pas de support explicite pour la gestion des noms de chemins dans la bibliothèque Javascript principale (ECMA), mais (au moins) Node.js fournit un support via le module Path.

Stephen C
la source
4
Quelque chose de similaire est également le cas pour les langages .Net Framework et tous ceux qui offrent des classes de système de fichiers.
James Snell
3
Merci! Cela semblait être la réponse la plus utile, même si chaque langage était spécifique, des bibliothèques devraient exister pour d'autres langages en général, tels que .NET et C ++;
iiridescent
3
En réalité, tout code qui n'utilise pas de bibliothèque devrait être rejeté lors de la révision du code. Dans de rares cas, aucune bibliothèque n'existe, la réponse serait d'en écrire une vous-même plutôt que de coller des chaînes brutes.
Gort le robot
C ++ a Boost :: système de fichiers , et C # a System.IO.Path
Mooing Duck
Python a os.path.join. PowerShell a join-path. Je voudrais ajouter quelque chose à cette réponse. J'ai constaté que si vous aviez besoin de chemins de fichiers multiples, votre code serait très fragile si vous supposiez que l'un d'entre eux avait des chemins de fichiers situés à des emplacements particuliers. L'utilisation de ces classes facilite non seulement la portabilité, mais elle gère également tous les cas de figure possibles (barre oblique des deux côtés à joindre, barre oblique d'un seul côté, aucune barre oblique entre les deux). Cette flexibilité est inestimable lorsque vous déposez des chemins de fichiers dans un fichier de configuration.
jpmc26
21

Notez que dans .NET, vous devez utiliser la méthode Path.Combine.

var path = System.IO.Path.Combine("assets", "sounds");

La raison en est qu’elle «connaît» les caractères corrects à utiliser lors de la construction des noms de dossier.

Cela supprime le "problème" de pré ou post-fixation.

Euh non
la source
4
os.path.join fait fondamentalement la même chose pour python
StarWeaver
Notez que path.combine ne vous empêche pas de vous inquiéter pour le séparateur: stackoverflow.com/questions/53102/…
jmoreno
1
@jmoreno - Dans mon exemple, il n'y a PAS de séparateur. La question à laquelle vous êtes lié a des séparateurs codés en dur et est fondamentalement fausse car le second chemin est un chemin absolu.
Erno
Soyez prudent avec cela, cependant. Je ne suis pas sûr de .NET, mais os.path.join('src', '../../../your_secret_stuff') est valide en Python; en d'autres termes, n'utilisez pas aveuglément ces méthodes lors de la saisie de l'utilisateur.
sapi
@sapi - Bien sûr, les entrées de l'utilisateur doivent toujours être filtrées, mais cela relève de la responsabilité du programmeur, pas de l'API.
Erno
5

Lors de la construction de chemins, j'utilise souvent une fonction qui ajoute la barre oblique finale si elle n’y figure pas déjà. Ensuite, les chemins peuvent être construits comme:

filename := fs( 'assets') + fs( 'images') + fs( 'icons') + 'some.png';

où fs () ajoute une barre oblique finale si nécessaire.

Grand maître b
la source
5

Les dossiers et les fichiers ne diffèrent que par un aspect: les dossiers se terminent par une barre oblique, contrairement aux fichiers. De plus, les chemins absolus commencent par un /cas où les chemins relatifs ne le sont pas. Si vous utilisez ceci systématiquement, concaténer les chemins et les fichiers ne devrait poser aucun problème.

var absolutepath = "/my/path/";
var relativepath = "css/";
var filename = "test.css";
var relativepathtofilename = "js/test.js";

var a = absolutepath + relativepath + filename; //Output: /my/path/css/test.css
var b = absolutepath + relativepathtofilename;  //Output: /my/path/js/test.js

Concaténer deux chemins absolus n'a aucun sens, car le deuxième chemin doit être relatif au premier. La concaténation de deux chemins relatifs ne pose pas de problème, mais peut conduire à un comportement indéfini si le programme ne sait pas où le chemin relatif est relatif.

Sumurai8
la source
Cela répond probablement mieux à ma question initiale, je pense que je comprends mieux les chemins de fichiers, bien que, comme l'ont dit Stephen C et Erno, les bibliothèques de langues constituent un meilleur premier pari. Cela explique mieux la convention cependant. Merci!
iiridescent
Les chemins de système de fichiers ou les URL?
MrWhite
1
À toutes fins utiles, vous pouvez également appliquer cela à uri. Un uri absolu commencerait par un protocole, mais à part cela, ce serait la même chose, je pense.
Sumurai8
Vous ne savez pas comment votre sortie fonctionne. Quand je le fais je reçois:var a = "/my/path" + "css/" + "test.css"; //Output: "/my/pathcss/test.css"
Damon
1
@ Damon j'ai fait une édition. absolutepathaurait dû se terminer par une barre oblique, parce que c'est un chemin. D'une manière ou d'une autre, j'ai oublié cela quand j'ai écrit ceci.
Sumurai8
4

Je pense qu'il n'y a pas de magie ou de "pratique courante" sur la manière de mettre en œuvre des chemins, mais la concaténation de chaînes n'est certainement pas la solution. Vous pouvez développer votre propre API pour traiter les cas, mais cela peut nécessiter des efforts. En particulier, vous devez faire attention aux différentes plates-formes. Par exemple, dans Windows, \le séparateur, tandis que dans les systèmes Unix, il /est le séparateur.

Je ne connais pas bien les bibliothèques Javascript, mais je suis sûr qu'il devrait exister des bibliothèques pour gérer ces cas. En Java, par exemple, vous pouvez utiliser l' API Path pour gérer les opérations de chemin indépendantes de la plate-forme.

Wickoo
la source
3
Windows prend en charge /le délimiteur de nom de fichier de chemin d'accès. Cela nécessite des bizarreries dans la ligne de commande, mais les API d'E / S sur fichier fonctionnent parfaitement avec une barre oblique.
Ruslan
en.wikipedia.org/wiki/… "l'API système Windows accepte les barres obliques. Tous les exemples Unix ci-dessus doivent donc fonctionner. Cependant, de nombreuses applications Windows interprètent une barre oblique à d'autres fins ou la traitent comme un caractère non valide, et vous obligent donc pour entrer une barre oblique inversée - notamment le shell cmd.exe (souvent appelé le "terminal" car il s'exécute généralement dans une fenêtre de terminal) ".
Mooing Duck
0

Ma préférence personnelle est la suivante:

var assets = "/images"

var sounds = assets+"/sounds"

J'utilise toujours des chemins absolus ( /images/...), cela me semble moins sujet aux erreurs. Il est également plus facile de l'utiliser var sounds = assets+"/sounds"car même si assetsune barre oblique de fin et vous avez fini avec /images//sounds, il serait toujours résoudre à /images/sounds. Le seul déni de responsabilité étant que cela dépend de votre gestionnaire de demandes. Apache semble bien le gérer (au moins certaines versions / configurations, voir http://www.amazon.com//gp//site-directory//ref=nav_sad ). Dans l’autre cas, vous vous retrouveriez avec /imagessounds, pas si mal à l’aise :) Il est également possible de vérifier les doubles barres obliques et de les nettoyer. Pas une option avec l'autre approche.

rpaskett
la source
11
Dans tous les contextes que je connaisse, un chemin commençant par un slash ( /) est un chemin absolu , pas un chemin relatif. Ou avez-vous voulu dire cela uniquement pour les sections de chemin autres que la première?
Bart van Ingen Schenau
@BartvanIngenSchenau Je suis tout à fait d'accord avec vous et je les appelle depuis des années, mais chaque fois que je lis un article écrit par un développeur front-end, il se réfère à eux comme des chemins relatifs. Je ne voulais pas faire de suppositions alors je suppose que j'ai choisi le moindre de deux maux ...? Maintenant que je sais que j'ai des gens de mon côté, je vais mettre à jour ma réponse :)
rpaskett
2
Pour les développeurs Web, il /somewheres'agit d'un chemin relatif, car il n'inclut pas l'hôte. Le navigateur le recherchera donc en fonction de l'hôte de la page en cours ... Dans le monde Web, il http://here/somewheres'agit d'un URI absolu et /somewhereelserelatif à celui-ci. Dans le monde du système de fichiers, /somewhereabsolu, venant de la racine /, et "quelque part" est relatif au répertoire de travail en cours.
Rob le
3
@RobY, rpaskett: Going by RFC3986 (le RFC qui définit les URI), http://here/somewhereest un URI avec un chemin absolu, /somewhereune référence relative avec un chemin absolu et somewhere/elseune référence relative avec un chemin relatif. Apparemment, dans ces cercles, "chemin relatif" est utilisé pour désigner une référence relative.
Bart van Ingen Schenau
1
@BartvanIngenSchenau: dans Windows, un chemin qui commence par une barre oblique est un chemin relatif et est relatif à CWD. fr.wikipedia.org/wiki/…
Mooing Duck, le
0

En Smalltalk, il est simple de définir la méthode / dans String afin qu’elle fonctionne comme suit:

'assets' / 'sounds' => 'assets/sounds'.
'assets/' / 'sounds' => 'assets/sounds'.
'assets' / '/sounds' => 'assets/sounds'.
'assets/' / '/sounds' => 'assets/sounds'.

Voici une implémentation simple de la méthode (vous pouvez l'améliorer):

/ aString
    | slash first second |
    slash := Directory separator.
    first := self.
    (first endsWith: slash) ifTrue: [first := first allButLast].
    second := aString.
    (second beginsWith: slash) ifTrue: [second := second allButFirst].
    ^first , slash , second

Remarque : vous pouvez également payer une plus grande attention aux cas frontaliers tels que '' / '', 'x/' / '', etc., afin de déterminer le comportement approprié.

Leandro Caniglia
la source