Récuperer un identifiant dans un nom de fichier avec une REGEXP
Fermé
AlBert38
-
Modifié par Whismeril le 18/09/2015 à 14:18
KX Messages postés 16760 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 12 février 2025 - 19 sept. 2015 à 21:51
KX Messages postés 16760 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 12 février 2025 - 19 sept. 2015 à 21:51
A voir également:
- Récuperer un identifiant dans un nom de fichier avec une REGEXP
- Fichier bin - Guide
- Comment ouvrir un fichier epub ? - Guide
- Comment réduire la taille d'un fichier - Guide
- Fichier rar - Guide
- Fichier .dat - Guide
3 réponses
Nexii
Messages postés
338
Date d'inscription
jeudi 13 mars 2014
Statut
Membre
Dernière intervention
14 mars 2017
585
18 sept. 2015 à 11:20
18 sept. 2015 à 11:20
[^S\-(.]*(S\d{2}[eE]\d{1,2}).*
Celle-ci semble fonctionner.
Amuse toi sur ce site : https://regexr.com/
Celle-ci semble fonctionner.
Amuse toi sur ce site : https://regexr.com/
Utilisateur anonyme
18 sept. 2015 à 14:20
18 sept. 2015 à 14:20
Bonjour, j'ai corrigé la coloration syntaxique dans ta question, voir ici comment bien l'utiliser.
KX
Messages postés
16760
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
12 février 2025
3 020
18 sept. 2015 à 19:21
18 sept. 2015 à 19:21
Bonjour,
Quelques remarques :
Pourquoi tester [sS] et [eE] alors que tu fais un toUpperCase qui te garantie d'avoir S et E et jamais s ou e ?
À l'inverse, si tu testes [sS] et [eE] et que ce qui t'intéresse ce sont juste des chiffres... tu n'as plus besoin du toUpperCase.
Avec \d{1,2} on se limite à 1 ou 2 chiffres par nombre, c'est peut-être suffisant mais c'est dommage de se limiter alors qu'un + permettrait d'avoir n'importe quel nombre.
Sans oublier ce qu'il peut y avoir avant ou après la partie qui matche que l'on peut simplement représenter par .*
Quant au groupe de capture il faut le placer au bon endroit, sachant que le groupe 0 correspond à toute la chaîne qui matche, et que les groupes spécifiques spécifiées par les parenthèses commencent à l'index 1.
Éventuellement on peut aussi s'arranger pour récupérer l'extension du fichier, ce qui évite de supposer que c'est effectivement un .avi alors que ça pourrait être autre chose.
Une bonne pratique maintenant : si tu as une boucle dont tout le corps est un if sans else (ce qui est ton cas), il est plus propre de prendre la condition inverse et d'utiliser un continue. On peut faire pareil pour une méthode et faire un return. Cela permet de limiter le nombre de niveaux d'imbrications
Enfin, par convention en Java, les chemins d'accès sont spécifiés avec / et pas \\ même pour Windows.
Quelques remarques :
Pourquoi tester [sS] et [eE] alors que tu fais un toUpperCase qui te garantie d'avoir S et E et jamais s ou e ?
À l'inverse, si tu testes [sS] et [eE] et que ce qui t'intéresse ce sont juste des chiffres... tu n'as plus besoin du toUpperCase.
Avec \d{1,2} on se limite à 1 ou 2 chiffres par nombre, c'est peut-être suffisant mais c'est dommage de se limiter alors qu'un + permettrait d'avoir n'importe quel nombre.
Sans oublier ce qu'il peut y avoir avant ou après la partie qui matche que l'on peut simplement représenter par .*
Quant au groupe de capture il faut le placer au bon endroit, sachant que le groupe 0 correspond à toute la chaîne qui matche, et que les groupes spécifiques spécifiées par les parenthèses commencent à l'index 1.
Éventuellement on peut aussi s'arranger pour récupérer l'extension du fichier, ce qui évite de supposer que c'est effectivement un .avi alors que ça pourrait être autre chose.
Une bonne pratique maintenant : si tu as une boucle dont tout le corps est un if sans else (ce qui est ton cas), il est plus propre de prendre la condition inverse et d'utiliser un continue. On peut faire pareil pour une méthode et faire un return. Cela permet de limiter le nombre de niveaux d'imbrications
Enfin, par convention en Java, les chemins d'accès sont spécifiés avec / et pas \\ même pour Windows.
import java.io.File; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Test { private static final Pattern PATTERN = Pattern.compile(".*[sS]\\d+[eE](\\d+).*(\\.[^.]*)"); public static void renameEpisodes(File directory, String renamePrefix) { if (!directory.isDirectory()) return; for (File file : directory.listFiles()) { if (!file.isFile()) continue; Matcher matcher = PATTERN.matcher(file.getName()); if (!matcher.matches()) continue; String num = matcher.group(1); String ext = matcher.group(2); file.renameTo(new File(directory, renamePrefix + num + ext)); } } public static void main(String[] args) { renameEpisodes(new File("C:/Users/CHFN5382/Downloads/Nouveau dossier"), "Ma série "); } }
Bonjour,
merci pour tes conseils, j'avais déjà commencer a refactorer mon code avec certain de tes conseil avant :) Mais je prend note de certain oubli en effet :)
voici la version avant ta réponse :
merci pour tes conseils, j'avais déjà commencer a refactorer mon code avec certain de tes conseil avant :) Mais je prend note de certain oubli en effet :)
voici la version avant ta réponse :
public static void main(String[] args) { long start = System.currentTimeMillis(); if (args.length == 0) { System.out.println( "USAGE : RenameSeriesFiles racineDuNomDeFichier [repertoire des fichier][-auto] \n -auto : repertoire courrant"); return; } String racine = args[0]; String root = args[1]; if (root == "-auto") { root = ".\\"; } System.out.println("root : " + root); System.out.println("serie : " + racine); renameProcess(root, racine); long end = System.currentTimeMillis(); System.out.println("temps de traitement : " + (end - start) + "ms"); } private static void renameProcess(String root, String prefixeNomFichier) { File dossier = new File(root); if (dossier.isDirectory()) { // Pattern pattern = // Pattern.compile("#^(.*)-S?([0-9]*)E([0-9]*)#i"); Pattern pattern = Pattern.compile("S\\d\\dE\\d\\d"); File[] files = dossier.listFiles(); System.out.println("nombre de fichiers trouvés : " + files.length + "\n"); int i = 0; int j = 0; for (File file : files) { if (!file.isDirectory()) { i++; String name = file.getName().toUpperCase(); String extension = name.substring(name.lastIndexOf(".")).toLowerCase(); //file.renameTo(new File(dossier.getPath() + "\\" + name.replaceAll(".S4E", ".S04E"))); Matcher mattcher = pattern.matcher(name); if (mattcher.find()) { j++; String identifiant = mattcher.group(0); String newName = "\\" + prefixeNomFichier + " " + identifiant + extension; System.out.println(file.getName()); System.out.println("rename >> " + newName + "\n"); File newFile = new File(dossier.getPath() + newName); if (!fileExistInDirectory(dossier, newFile.getName())) { file.renameTo(new File(dossier.getPath() + newName)); } else { System.err.println("un fichier porte déjà ce nom dans le dossier : " + newFile.getName()); } } else { System.err.println( "l'identifiant de l'episode n'a pas été trouvé pour le fichier : " + file.getName()); } } } System.out.println("nombre de fichiers : " + i); System.out.println("nombre de repertoires : " + (files.length - i)); System.out.println("nombre de fichiers renomés : " + j); } } private static boolean fileExistInDirectory(File directory, String fileName) { boolean result = false; if (directory.isDirectory() && fileName != null) { for (File file : directory.listFiles()) { if (fileName.equals(file.getName())) { return true; } } } else { result = true; } return result; }
KX
Messages postés
16760
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
12 février 2025
3 020
>
AlBert38
19 sept. 2015 à 15:53
19 sept. 2015 à 15:53
Ce genre de code ne fonctionne pas :
Pour la partie renommage des fichiers je te laisse regarder ma réponse d'hier.
if (root == "-auto")parce que la comparaison avec == compare les objets pas leurs valeurs et qu'il est impossible que args[1] soit le même objet que "-auto" même s'ils ont la même valeur, de plus en récupérant args[1] tu supposes que args.length>=2 or la seule chose que tu testes c'est que si args.length!=0 ce qui est insuffisant.
public static void main(String[] args) { long start = System.currentTimeMillis(); if (args.length < 2) { System.err.println("USAGE: RenameSeriesFiles racineDuNomDeFichier [repertoire des fichier][-auto]"); System.err.println(" -auto : repertoire courant"); return; } String racine = args[0]; String root = args[1]; if (root.equals("-auto")) root = ".\\"; // à tester: "" ou new File().getPath() ...
Pour la partie renommage des fichiers je te laisse regarder ma réponse d'hier.
AlBert38
>
KX
Messages postés
16760
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
12 février 2025
19 sept. 2015 à 20:39
19 sept. 2015 à 20:39
oui je le sais en plus pour le .equals() c'est du code pas testé juste écris de manière compulsive en regardant des séries en même temps :)
j'avais dupliquer un ligne sur un test de lenght (donc du int primitif)
et pour le equals pour ma part je l'utilise plutot dans l'autre sens
j'avais dupliquer un ligne sur un test de lenght (donc du int primitif)
et pour le equals pour ma part je l'utilise plutot dans l'autre sens
"-auto".equals(root)comme ca c'est null safe :D
KX
Messages postés
16760
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
12 février 2025
3 020
19 sept. 2015 à 21:51
19 sept. 2015 à 21:51
Remarque :
Généralement on mets
De toute façon args[1] ne peut pas être null... donc root non plus, du coup
Et s'il y avait un risque d'avoir null, il serait mieux de tester explicitement la valeur avec un
Exemple, dans ton cas c'est la méthode equals de la classe String, voici son code :
Le cas où anObject est null est géré par instanceof qui renvoie false, mais la méthode a d'abord testé
Généralement on mets
x.equals(y)lorsque c'est la variable
x
qui nous intéresse et que l'on regarde la valeur y
. Dans ton cas il serait plus logique de mettre root.equals(AUTO)
De toute façon args[1] ne peut pas être null... donc root non plus, du coup
AUTO.equals(root)ou
root.equals(AUTO)les deux ne posent aucun risque.
Et s'il y avait un risque d'avoir null, il serait mieux de tester explicitement la valeur avec un
if (x==null)plutôt que déléguer ce contrôle à une méthode qui même si elle gère le cas peut faire plusieurs opérations avant de contrôler la valeur null.
Exemple, dans ton cas c'est la méthode equals de la classe String, voici son code :
public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { ... } return false; }
Le cas où anObject est null est géré par instanceof qui renvoie false, mais la méthode a d'abord testé
this == anObjectau préalable, ce qui est inutile... on aurait tout simplement pu ne jamais appeler la méthode equals.
18 sept. 2015 à 14:12
merci cela ne correspondait pas exactement a ce que je voulais mais je l'ai adapté :
([sS]\d{1,2}[eE]\d{1,2})
, je souhaite que seul le numéro de l'épisode match en fait, j'écrase le reste du nom de fichier
en tous cas merci pour le site il est génial !