IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Rust Discussion :

[Rust 1.72.1][fs::rename] renommer un fichier dans une boucle traitant des DirEntry


Sujet :

Rust

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre expérimenté

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    330
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 330
    Par défaut [Rust 1.72.1][fs::rename] renommer un fichier dans une boucle traitant des DirEntry
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
       let mut iterator_folder = fs::read_dir(target.clone());             
                    ...
                    'parcourir:  for fichier in iterator_folder.as_mut().unwrap()
    		{
    			// on ne traite que les répertoires et les fichiers, pas les liens symboliques
    			if fichier.as_ref().unwrap().file_type().unwrap().is_dir()
    			{
    				...
    			}
    			else
    			{
    				if String::from(fichier.as_ref().unwrap().file_name().to_str().unwrap()).ends_with(SUFFIX) // SUFFIX équivaut à ".mp4"
    				{
    					// Traitement des noms de joueurs contenant des caractères interdits dans les noms de fichiers
    					// TODO: trouver une solution
     
    					if String::from(fichier.as_ref().unwrap().file_name().to_str().unwrap()).contains(QUESTION) // QUESTION équivaut à "(qm)"
    					{
    						println!("[DEBUG 1] {:?}",fichier); // (qm)test(qm).mp4
    						let processedfilename = fichier.as_ref().unwrap().file_name().to_str().unwrap().replace(QUESTION,"?");
    						let result = rename(fichier.as_ref().unwrap().file_name(),processedfilename);
    						if result.is_err()
    						{
    							eprintln!("rename ERROR -> {}",result.unwrap_err());
    						}
    						println!("[DEBUG 2] {:?}",fichier); // toujours (qm)test(qm).mp4 mais sur le système de fichiers c'est ?test?.mp4
    					}
    				...
    		} // end for
    Je pensais avec ces instructions renommer un fichier...
    Effectivement sur le disque dur le fichier est bien renommé... le soucis dans cette boucle c'est que à la suite de celle-ci comme "fichier" n'a pas vu son champs "filename" modifié, j'ai une erreur "file not found"
    lorsque j'essaye d'accéder au fichier renommé...

    Je ne vois pas du tout comment faire pour associer "processedfilename" au champs retourné par file_name()...
    Au pire je pourrais "court-circuiter l'iterator" en essayant de relire les fichiers contenus dans le répertoire que je suis en train de parcourir, au départ je pensais faire un "rewind" d'un élément mais je ne sais pas comment faire cela avec un iterator...

    iterator_folder -= 1 ? // mon rustrover n'a pas l'air fort content...

    PS: fichier n'est pas mutable mais il n'existe pas de "setter" dans ses "traits" je ne vois pas du tout comment procéder pour que DEBUG 1 et DEBUG 2 indiquent quelque chose de cohérent...

    [EDIT]

    iterator_folder = fs::read_dir(target.clone()); // ça ne marche pas
    (cannot assign to `iterator_folder` because it is borrowed)
    ...et comme je ne comprends absolument rien au concept d'emprunt là je bouquine et je galère...

  2. #2
    Membre Expert
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 513
    Par défaut
    Bonjour,

    Citation Envoyé par hurukan Voir le message
    PS: fichier n'est pas mutable mais il n'existe pas de "setter" dans ses "traits" je ne vois pas du tout comment procéder pour que DEBUG 1 et DEBUG 2 indiquent quelque chose de cohérent...
    Ta variable fichier est de type Result<std::fs::DirEntry, std::io::Error>. Elle est effectivement immuable. Techniquement, il est possible de la rendre muable en remplaçant for fichier in par for mut fichier in, mais cela ne te servira à rien.

    La fonction std::fs::rename prend deux paramètres convertibles en chemins de fichier : le chemin de départ (avant renommage) et le chemin d'arrivée (après renommage). Pour manipuler le fichier après renommage, il faut donc laisser tomber le chemin de départ et utiliser le chemin d'arrivée : println!("[DEBUG 2] {:?}", processedfilename);Attention que le code actuel suppose que le nom du fichier (processedfilename) équivaut à son adresse, donc que le fichier se trouve dans le répertoire courant.

    Citation Envoyé par hurukan Voir le message
    iterator_folder = fs::read_dir(target.clone()); // ça ne marche pas
    (cannot assign to `iterator_folder` because it is borrowed)
    ...et comme je ne comprends absolument rien au concept d'emprunt là je bouquine et je galère...
    La boucle for itère sur l'itérateur à l'intérieur de ta variable iterator_folder donc, en effet, à l'intérieur de la boucle, le borrow checker t'empêchera de réaffecter la variable iterator_folder. Mais je ne vois pas quel sens cela aurait de faire ça à l'intérieur de la boucle.

  3. #3
    Membre expérimenté

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    330
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 330
    Par défaut
    Oui...

    Je tente -- pour ne pas devoir le faire manuellement -- de renommer des fichiers qui n'acceptent pas certains caractères...
    J'ai donc une liste de patterns qui seront remplacés par les caractères correspondants automatiquement convertis en leur équivalent utf8 -- (qm) -> ? (pp) -> | etc... -- ce qui est, d'après mes tests, fonctionnel sur la plupart des systèmes de fichiers.

    Je lis le contenu d'un répertoire donné, et je cherche tous ces fichiers et tente de remplacer tous ces patterns tout en renommant les fichiers.
    Le soucis c'est que l'objet qui est extrait semble être "en lecture seule" -- impossible de modifier le nom du fichier -- donc du coup, un peu plus tard quand j'essaye d'accéder au fichier renommé j'ai un "file not found" :{

    Je pourrais passer par une autre variable mais ce qui me pose soucis c'est que j'ai l'habitude d'extraire d'une liste ou stack ou linkedlist et directement "travailler" sur cet objet, ça me fait mal au crâne de devoir extraire un objet et de passer par une variable secondaire
    pour obtenir quelque chose de fonctionnel. Je trouve cela complètement illogique.

    D'autant que je calcule un Hash en utilisant "l'objet" fichier... ce Hash se retrouve dans une base de données et me permet d'éviter les doublons, si je change ma manière de calculer le Hash je vais me retrouver avec plus de 5000 doublons à gérer par la suite :{
    Bon il est vrai que les "noms de joueurs" figurant dans le nom des fichiers qui contiennent des caractères interdits dans les "paths" de systèmes de fichiers sont rares mais ça me gave de devoir aller rechercher les caractères (représentations) sur internet et les insérer manuellement.

    Je n'ai pas encore la possibilité de faire un MiM pour essayer de détecter le nom du joueur en temps réel, pendant que je joue au jeu vidéo en question. J'ai déjà essayé avec wireshark, tout est chiffré ça sert pas à grand chose.
    L'idée serait la suivante: je créerais les fichiers à partir de ces informations et le problème des caractères ne se poserait plus, tous mes systèmes de fichiers sont utf8... et les méthodes du crate std::fs semblent convenir parfaitement -- d'après mes tests.

  4. #4
    Membre Expert
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 513
    Par défaut
    Citation Envoyé par hurukan Voir le message
    Je pourrais passer par une autre variable mais ce qui me pose soucis c'est que j'ai l'habitude d'extraire d'une liste ou stack ou linkedlist et directement "travailler" sur cet objet, ça me fait mal au crâne de devoir extraire un objet et de passer par une variable secondaire
    pour obtenir quelque chose de fonctionnel. Je trouve cela complètement illogique.
    Dans ce cas, tu peux faire quelque chose qui ressemble à ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    use std::path::PathBuf;
     
    fn main() {
        let mut paths = vec![PathBuf::from("/foo/bar"), PathBuf::from("/foo/mare")];
        for path in &mut paths {
            let file_name = path.file_name().unwrap().to_str().unwrap();
            let new_file_name = file_name.replace('r', "z");
            let old_path = path.clone();
            path.set_file_name(new_file_name);
            println!("Rename {old_path:?} to {path:?} and work with {path:?}.");
        }
        assert!(paths == vec![PathBuf::from("/foo/baz"), PathBuf::from("/foo/maze")]);
    }
    Une fois qu'on a une collection muable de chemins, on peut itérer dessus et, à chaque itération, modifier le chemin courant si on le souhaite.

    Dans ton cas, cela implique de parcourir une première fois le résultat de std::fs::read_dir pour construire la collection.

    Citation Envoyé par hurukan Voir le message
    D'autant que je calcule un Hash en utilisant "l'objet" fichier... ce Hash se retrouve dans une base de données et me permet d'éviter les doublons, si je change ma manière de calculer le Hash je vais me retrouver avec plus de 5000 doublons à gérer par la suite :{
    Cela m'étonnerait que tu parles de la variable fichier de type Result<std::fs::DirEntry, std::io::Error> dans ton précédent code, car std::fs::DirEntry n'implémente pas le trait std::hash::Hash.

    Citation Envoyé par hurukan Voir le message
    tous mes systèmes de fichiers sont utf8
    Du coup, tu devrais aimer le crate camino qui évitera certains appels à .to_str().unwrap(). Par exemple camino::Utf8Path::file_name retourne directement un Option<&str>, tandis que std::path::Path::file_name retourne un Option<&OsStr>.

  5. #5
    Membre expérimenté

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    330
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 330
    Par défaut
    ...merci pour le coup de main et les alternatives proposées, je vais tenter quelque chose...

  6. #6
    Membre expérimenté

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    330
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 330
    Par défaut
    Voilà, tout cela repose sur ma non connaissance complète des possiblités de Rust ^^

    J'ai résolu mon soucis simplement en faisant ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    FILENAMES.push
    (
      String::from(fichier.as_ref().unwrap().file_name().into_string().unwrap().clone())
      .replace(QUESTION,"?")
    );
    ...je me suis focalisé sur "l'objet" fichier alors qu'en fait, au final, je ne manipule que des chaînes de caractères...

    A priori ça à l'air de tenir la route mais je ne renomme pas le fichier... en soi c'est dommage mais dans la base de données le nom du joueur est, lui, correct...

    sirius:/2023 # uepMagicStats
    uep_magicstats2023 (version 1.0.0 2023 by Hurukan) RUST 1.72.1
    Current directory: /2023
    Connected to the database...
    Objects in FILENAMES: 1
    Ignoring -> troisième test à effacer EPIC.mp4 [H 8596d7f707989df25de3fc581039ec10]
    Inserts in FDP: 0
    Inserts in CMTS: 0
    [INFO] updateVector() -- 5367 adds in mon_tableau_de_chasse
    +-------+--------+-----------+--------------+
    | idFDP | NomFDP | Poutrages | ref_Comments |
    +-------+--------+-----------+--------------+
    | 5457 | ???? | 2 | 9138 |
    +-------+--------+-----------+--------------+
    1 row in set (0.000 sec)
    Reste plus qu'à faire en sorte de renommer le fichier, je pense que c'est possible tout à la fin de la boucle après que tous les traitements aient été effectués...

    [EDIT]
    En fait non, je suis c...
    Tant que je n'arrive pas à manipuler les "itérateurs" de manière à "recommencer au début" (relire le contenu du répertoire courant avec un nouvel appel à read_dir() ) ça ne fonctionnera jamais...
    J'ai bien essayé mais ça ne marche pas, iterator_folder semble conserver son "curseur" et je n'arrive pas à faire en sorte que le répertoire soit "rafraichi" :{

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 1
    Dernier message: 09/12/2008, 12h23
  2. renommer un mot dans une table
    Par dztcid dans le forum SQL Procédural
    Réponses: 7
    Dernier message: 26/05/2008, 15h15
  3. [Fortran 77] Renommer un fichier dans une boucle
    Par mehdi_oca dans le forum Fortran
    Réponses: 3
    Dernier message: 04/01/2008, 14h38
  4. Renommer un fichier dans une boucle
    Par Thomas Carrere dans le forum C
    Réponses: 5
    Dernier message: 05/05/2006, 18h20
  5. [SQL] Renommer un champ dans une requête
    Par martonpylon12 dans le forum Requêtes et SQL.
    Réponses: 8
    Dernier message: 15/11/2003, 01h59

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo