OVH Cloud OVH Cloud

Nettoyer les chemins de fichier

10 réponses
Avatar
Yves Martin
Bonjour,

Je cherche un moyen de nettoyer des chemins du type:
~/dir1/../dir2
~/dir1/../dir2/f1
~/dir1/./dir2/f1
/dir1/../dir2
/dir1/../dir2/f1
/dir1/./dir2/f1

J'ai trouvé Cwd->realpath qui résoud les ./ et ../ mais ses gros
défauts sont:
. il ne comprend pas ~/
. il résoud les liens symboliques
. comme il résoud sur le système de fichier, un répertoire ou fichier
qui n'existe pas devient undef

Les résultats que j'attends sont évidemment:

~/dir1/../dir2 -> ~/dir2
~/dir1/../dir2/f1 -> ~/dir2/f1
~/dir1/./dir2/f1 -> ~/dir1/dir2/f1
/dir1/../dir2 -> /dir2
/dir1/../dir2/f1 -> /dir2/f1
/dir1/./dir2/f1 -> /dir1/dir2/f1

quelque soit l'état du système de fichiers (fichier ou répertoire
inexistant ou lien symbolique) et si c'est multi-plateforme c'est
encore mieux.

Oui, j'en demande beaucoup mais je me renseigne avant de faire le
code à coup de File::Spec splitpath, catpath, splitdir, catdir

Si vous avez des tuyaux sur des modules qui feraient cela, je vous en
remercie par avance.
Salutations,
--
Yves Martin

10 réponses

Avatar
Patrick Mevzek
Oui, j'en demande beaucoup mais je me renseigne avant de faire le code
à coup de File::Spec splitpath, catpath, splitdir, catdir


File::Spec->canonpath() ne suffit pas ? (pas testé)

--
Patrick Mevzek . . . . . . Dot and Co (Paris, France)
<http://www.dotandco.net/> <http://www.dotandco.com/>

Avatar
Yves Martin
Patrick Mevzek writes:

Oui, j'en demande beaucoup mais je me renseigne avant de faire le code
à coup de File::Spec splitpath, catpath, splitdir, catdir


File::Spec->canonpath() ne suffit pas ? (pas testé)


Non, j'ai déjà essayé. C'est OK pour les ./ mais pas pour ../

my @testCase = (
"~/dir1/../dir2",
"~/dir1/../dir2/f1",
"~/dir1/./dir2/f1",
"/dir1/../dir2",
"/dir1/../dir2/f1",
"/dir1/./dir2/f1",
);

print "Result: " . join( " ", map { File::Spec->canonpath($_) } @testCase ) . "n";


Result: ~/dir1/../dir2 ~/dir1/../dir2/f1 ~/dir1/dir2/f1 /dir1/../dir2 /dir1/../dir2/f1 /dir1/dir2/f1

--
Yves Martin


Avatar
Patrick Mevzek
Oui, j'en demande beaucoup mais je me renseigne avant de faire le
code à coup de File::Spec splitpath, catpath, splitdir, catdir


File::Spec->canonpath() ne suffit pas ? (pas testé)


Non, j'ai déjà essayé. C'est OK pour les ./ mais pas pour ../


Pourtant le code les gère bien, mais la regex est ancrée sur le début de
la chaine, donc cela ne gère pas les .. au milieu
(mais ca gère bien les /./ n'importe où...)

--
Patrick Mevzek . . . . . . Dot and Co (Paris, France)
<http://www.dotandco.net/> <http://www.dotandco.com/>



Avatar
Denis -esp2008-
Bonjour,

Les résultats que j'attends sont évidemment:

~/dir1/../dir2 -> ~/dir2
~/dir1/../dir2/f1 -> ~/dir2/f1
~/dir1/./dir2/f1 -> ~/dir1/dir2/f1
/dir1/../dir2 -> /dir2
/dir1/../dir2/f1 -> /dir2/f1
/dir1/./dir2/f1 -> /dir1/dir2/f1

quelque soit l'état du système de fichiers (fichier ou répertoire
inexistant ou lien symbolique) et si c'est multi-plateforme c'est
encore mieux.


Méthode de paresseux (on ne programme pas en perl pour rien;):

$chemin =~ s!/[a-zA-Z0-9]+/..!!;
$chemin =~ s!(/[a-zA-Z0-9]+)/.!$1!;

Bonne chance;

--
Denis

Avatar
Denis -esp2008-
Méthode de paresseux (on ne programme pas en perl pour rien;):


D'ailleurs elle ne marche que pour les exemples qui étaient donnés ici,
deux /.. qui se suivent et c'est foutu.

--
Denis

Avatar
Yves Martin
Patrick Mevzek writes:

Oui, j'en demande beaucoup mais je me renseigne avant de faire le
code à coup de File::Spec splitpath, catpath, splitdir, catdir


File::Spec->canonpath() ne suffit pas ? (pas testé)


Non, j'ai déjà essayé. C'est OK pour les ./ mais pas pour ../


Pourtant le code les gère bien, mais la regex est ancrée sur le début de
la chaine, donc cela ne gère pas les .. au milieu
(mais ca gère bien les /./ n'importe où...)


Je n'ai pas regardé le code. Mais dans ce cas, est-ce que l'on peut
considérer ce "défaut" de canonpath comme un bug à corriger ?

--
Yves Martin




Avatar
Yves Martin
Denis -esp2008- writes:

Méthode de paresseux (on ne programme pas en perl pour rien;):


D'ailleurs elle ne marche que pour les exemples qui étaient donnés ici,
deux /.. qui se suivent et c'est foutu.


Et oui, ce n'est pas si simple à faire et pour être multi-platforme
il faut utiliser les séparateurs spécifiques... Bref, il est
nécessaire de découper le chemin avec splitpath, découper ensuite les
répertoires avec splitdir et analyser la liste pour supprimer les
éléments "réduits" par ../
Ce n'est qu'une boucle avec des opérations de pile/liste mais il faut
le faire correctement et complètement (pas comme canonpath !)

<troll> quand je pense que Java fait cela super bien... </troll>

--
Yves Martin


Avatar
Patrick Mevzek
Je n'ai pas regardé le code.


$path =~ s|^/(../)+|/|s; # /../../xx -> xx

Mais dans ce cas, est-ce que l'on peut
considérer ce "défaut" de canonpath comme un bug à corriger ?


Je trouve qu'on peut le considérer comme un défaut oui, mais peut-être
qu'il y a une autre explication.

--
Patrick Mevzek . . . . . . Dot and Co (Paris, France)
<http://www.dotandco.net/> <http://www.dotandco.com/>

Avatar
Rue des Prairies
Yves Martin wrote:
Bonjour,

Je cherche un moyen de nettoyer des chemins du type:
~/dir1/../dir2
~/dir1/../dir2/f1
~/dir1/./dir2/f1
/dir1/../dir2
/dir1/../dir2/f1
/dir1/./dir2/f1

J'ai trouvé Cwd->realpath qui résoud les ./ et ../ mais ses gros
défauts sont:
. il ne comprend pas ~/
. il résoud les liens symboliques
. comme il résoud sur le système de fichier, un répertoire ou fichier
qui n'existe pas devient undef

Les résultats que j'attends sont évidemment:

~/dir1/../dir2 -> ~/dir2
~/dir1/../dir2/f1 -> ~/dir2/f1
~/dir1/./dir2/f1 -> ~/dir1/dir2/f1
/dir1/../dir2 -> /dir2
/dir1/../dir2/f1 -> /dir2/f1
/dir1/./dir2/f1 -> /dir1/dir2/f1

quelque soit l'état du système de fichiers (fichier ou répertoire
inexistant ou lien symbolique) et si c'est multi-plateforme c'est
encore mieux.

Oui, j'en demande beaucoup mais je me renseigne avant de faire le
code à coup de File::Spec splitpath, catpath, splitdir, catdir

Si vous avez des tuyaux sur des modules qui feraient cela, je vous en
remercie par avance.
Salutations,



Bonsoir,
essaie ceci :
s![^/]+/.{1,2}/!!;

en remplaçant / par le délimiteur propre à l'OS.

Olivier.

Avatar
David LE BOURGEOIS
Bonjour,


Bonjour.


Je cherche un moyen de nettoyer des chemins du type:
~/dir1/../dir2
~/dir1/../dir2/f1
~/dir1/./dir2/f1
/dir1/../dir2
/dir1/../dir2/f1
/dir1/./dir2/f1

J'ai trouvé Cwd->realpath qui résoud les ./ et ../ mais ses gros
défauts sont:
. il ne comprend pas ~/
. il résoud les liens symboliques
. comme il résoud sur le système de fichier, un répertoire ou fichier
qui n'existe pas devient undef

Les résultats que j'attends sont évidemment:

~/dir1/../dir2 -> ~/dir2
~/dir1/../dir2/f1 -> ~/dir2/f1
~/dir1/./dir2/f1 -> ~/dir1/dir2/f1
/dir1/../dir2 -> /dir2
/dir1/../dir2/f1 -> /dir2/f1
/dir1/./dir2/f1 -> /dir1/dir2/f1

quelque soit l'état du système de fichiers (fichier ou répertoire
inexistant ou lien symbolique) et si c'est multi-plateforme c'est
encore mieux.

Oui, j'en demande beaucoup mais je me renseigne avant de faire le
code à coup de File::Spec splitpath, catpath, splitdir, catdir

Si vous avez des tuyaux sur des modules qui feraient cela, je vous en
remercie par avance.
Salutations,


Un coup de canonpath suivi d'une analyse avec une pile ?


#!/usr/bin/perl -w

use strict;
use File::Spec;

my $SEP = '/';

die "$0 : chemin manquantn" unless defined $ARGV[0];

my @path = ();
foreach my $token (split $SEP, File::Spec->canonpath($ARGV[0])) {
if($token eq '..') { pop @path }
else { push @path, $token }
}
print join $SEP, @path; print "n";


Le problème avec la pile se pose avec les chemins relatifs au
répertoire courant. Par exemple avec ../../a, on dépile une pile vide.
Une solution serait peut-être de nettoyer le début du chemin avant de
commencer l'analyse.


--
David LE BOURGEOIS