cincap
Messages postés460Date d'inscriptiondimanche 5 décembre 2004StatutMembreDernière intervention 6 avril 2009
-
25 janv. 2007 à 19:59
cincap
Messages postés460Date d'inscriptiondimanche 5 décembre 2004StatutMembreDernière intervention 6 avril 2009
-
29 janv. 2007 à 14:25
Bonsoir,
J'ai un petit souci avec une procédure pour renommer une série de fichiers.
Si les fichiers en questions ont déjà été renommé avec le nouveau nom ajouté du signe "_0" puis de son extension, cela fonctionne la 1ère fois.
Par contre si je modifie le nom renommé, le new nom devient farfelu "_0100" etc.
Voici le code que j'utilise :
Edit1 = le chemin
Edit2 = new nom
Edit3 = extension
procedure TFiche.But_RenommerClick(Sender: TObject);
Var
IndexFichier, NombreFichiers, Rep: integer ;
Info : TSearchRec;
Fichier, MonExtensionDeFichier, NouveauNomDeFichier, Chemin, FichierRenomme: string ;
begin
Chemin := IncludeTrailingPathDelimiter(Edit1.Text);
NouveauNomDeFichier := edit2.Text;
If FindFirst(Chemin+ edit3.text,faAnyFile,Info)=0 Then
NombreFichiers :=0 ;
Begin
Repeat
NombreFichiers := NombreFichiers + 1 ;
Until FindNext(Info)<>0;
end;
Rep : = Application.MessageBox(Pchar('*** Etes vous certain de vouloir renommer ces '+IntToStr(NombreFichiers)+' fichiers ***' ), 'Message ', MB_OKCANCEL );
If Rep = 1 then // si l'utilisateur a
begin
ProgressBar1.Min := 0;
ProgressBar1.Max := NombreFichiers;
ProgressBar1.Position := 0 ;
{ Recherche de la première entrée du répertoire }
If FindFirst(Chemin+ edit3.text,faAnyFile,Info)=0 Then
Begin
IndexFichier := +1 ;
Repeat
Fichier := Info.FindData.cFileName; // on recupere le nom du fichier
MonExtensionDeFichier := ExtractFileExt(Fichier); // on recupere l'extension
FichierRenomme := Chemin + NouveauNomDeFichier + '_0'+ IntToStr(IndexFichier)+ MonExtensionDeFichier;
RenameFile(Chemin + Fichier, FichierRenomme);
// compte les fichiers
IndexFichier := IndexFichier +1;
ProgressBar1.Position := ProgressBar1.Position +1 ;
Until FindNext(Info)<>0;
FindClose(Info);
Application.MessageBox(Pchar('*** Les '+IntToStr(NombreFichiers)+' fichiers sont renommés avec succès ! ***'), 'Message', MB_OK) ;
end;
end;
JulioDelphi
Messages postés2226Date d'inscriptiondimanche 5 octobre 2003StatutMembreDernière intervention18 novembre 201014 25 janv. 2007 à 20:17
resalut !
déjà, je ne vois pas de question =) donc je ne sais pas quel est ton probleme, ce que tu as essayé ou a quel endroit tu bloques.
si j'essaie de deviner, voila ce que j'en sors :
j'ai un fichier "bonjour.txt", je le passe au renommeur, j'obtiens "bonjour_01.txt".
Si je passe a nouveau le fichier au renommeur, j'obtiens "bonjour_01_01.txt" ce qui est totalement logique.
Est-ce que c'est ça que tu veux eviter ? c'est plutot à l'utilisateur de ne pas renommer 2 fois les fichiers ! sous peine d'obtenir de genre de resultats.
Si je me trompe de probleme, merci de l'xpliquer plus clairement.
cincap
Messages postés460Date d'inscriptiondimanche 5 décembre 2004StatutMembreDernière intervention 6 avril 20092 25 janv. 2007 à 22:59
Bonsoir,
@ JulioDelphi, c'est en fait ce que tu as deviné.
Je pensais que le fait de renommer éffacerai l'ancien nom donc "bonjour.txt" j'obtiens "bonjour_01.txt" ce qui est logique, mais par contre si je le renomme, cela devrai effacer "bonjour_01" et avoir le new nom.
Je me trompe peut-être.
Maintenant ta réponse est pertinente quand tu dis que c'est à l'utilisateur de ne pas renommé 2 x le même fichier.
JulioDelphi
Messages postés2226Date d'inscriptiondimanche 5 octobre 2003StatutMembreDernière intervention18 novembre 201014 25 janv. 2007 à 23:17
Autre exemple :
voila ma liste de fichiers :
"bonjour.txt
salut.txt
machin.txt"
je les renomme avec la maniere 1, j'obtiens :
"bonjour.txt > bonjour_01.txt
salut.txt > salut_02.txt
machin.txt > machin_03.txt"
mais tu peux aussi demande un prefixe de nom de fichier, ce qui me donnerais avec le prefixe "julio":
"bonjour.txt >julio_01.txt
cincap
Messages postés460Date d'inscriptiondimanche 5 décembre 2004StatutMembreDernière intervention 6 avril 20092 26 janv. 2007 à 11:13
Bonjour,
@ JulioDelphi, je viens de tester ton exemple avec le code cité dans mon 1er message, avant tout il faut mettre déjà un new nom dans le Tedit 2 sinon on aura uniquement ceci : "_01.txt, _02.txt, _03.txt,_04.txt, _05.txt" (5 fichiers).
Si je met Julio, j'obtiens "Julio_01.txt, Julio_02.txt, Julio_03.txt, Julio_04.txt, Julio_05.txt" ce qui est le but.
Maintenant je renomme Julio en Juli (ou j'éfface le o) et j'obtiens "Juli_02.txt, Juli_03.txt, Juli_04.txt, Juli_05.txt, Juli_06.txt".
Le Juli_01.txt est disparu par contre à ce stade, si sans rien changer, je clique à nouveau sur le bouton "renommer" l'ordre est à nouveau correct et j'obtiens
"Juli_01.txt, Juli_02.txt, Juli_03.txt, Juli_04.txt, Juli_05.txt".
Dans la fonction citée plus haut, il y a bien un bug mais je ne trouve pas ou.
ThWilliam
Messages postés418Date d'inscriptionmardi 3 janvier 2006StatutMembreDernière intervention26 novembre 20134 26 janv. 2007 à 18:29
Salut cincap,
j'ai un peu retravaillé ta procedure et tout marche (changement en 'julio', puis 'juli' avec edit3.text = '*.*'
Attention : chaque fois que tu emploies un FindFirst, tu dois libérer avec FindClose ce que tu ne fais pas après la 1° recherche (pour nb de fichiers) et incorrectement la 2° fois puisque FindClose est dans le begin...end du if findfirst = 0... donc pas de FindClose si FindFirst était <> 0 (ce qui n'arrive pas ici, d'accord).
procedure TFiche.But_RenommerClick(Sender: TObject);
Var
IndexFichier, NombreFichiers, Rep: integer ;
Info : TSearchRec;
Fichier, MonExtensionDeFichier, NouveauNomDeFichier, Chemin, FichierRenomme: string ;
begin
Chemin := IncludeTrailingPathDelimiter(Edit1.Text);
NouveauNomDeFichier := edit2.Text;
NombreFichiers :=0 ;
If FindFirst(Chemin+ edit3.text,faAnyFile,Info)=0 Then
Repeat
NombreFichiers := NombreFichiers + 1 ;
Until FindNext(Info)<>0;
FindClose(Info);
if (NombreFichiers > 0) and
(Application.MessageBox(Pchar('*** Etes vous certain de vouloir renommer ces '+IntToStr(NombreFichiers)+' fichiers ***' ),
'Message ', MB_OKCANCEL) = IDOK) then
begin
ProgressBar1.Min := 0;
ProgressBar1.Max := NombreFichiers;
ProgressBar1.Position := 0 ;
try
If FindFirst(Chemin+ edit3.text,faAnyFile,Info)=0 Then
Begin
IndexFichier := 1 ;
Repeat
Fichier := Info.FindData.cFileName; // on recupere le nom du fichier
MonExtensionDeFichier := ExtractFileExt(Fichier); // on recupere l'extension
FichierRenomme := Chemin + NouveauNomDeFichier + '_0'+ IntToStr(IndexFichier)+ MonExtensionDeFichier;
RenameFile(Chemin + Fichier, FichierRenomme);
// compte les fichiers
IndexFichier := IndexFichier +1;
ProgressBar1.Position := ProgressBar1.Position +1 ;
Until FindNext(Info)<>0;
end;
Application.MessageBox(Pchar('*** Les '+IntToStr(NombreFichiers)+' fichiers sont renommés avec succès ! ***'), 'Message', MB_OK) ;
finally
FindClose(Info);
end;
end;
end;
ThWilliam
Messages postés418Date d'inscriptionmardi 3 janvier 2006StatutMembreDernière intervention26 novembre 20134 26 janv. 2007 à 19:28
Re-cincap,
de fait, à force de tester, j'obtiens aussi la même chose : cela est dû, à mon avis, à l'emploi d'une boucle FindNext alors qu'on fait des opérations sur les fichiers.
Il faut une autre méthode: stockage des fichiers en mémoire.
J'essaie le code et puis je le poste.
ThWilliam
Messages postés418Date d'inscriptionmardi 3 janvier 2006StatutMembreDernière intervention26 novembre 20134 26 janv. 2007 à 19:55
En stockant les noms de fichiers à renommer dans un TStringList, plus de problèmes.
procedure TFiche.But_RenommerClick(Sender: TObject);
Var
IndexFichier: integer ;
Info : TSearchRec;
Fichier, MonExtensionDeFichier, NouveauNomDeFichier, Chemin, FichierRenomme: string ;
MaListe: TStringList;
I: integer;
begin
Chemin := IncludeTrailingPathDelimiter(Edit1.Text);
NouveauNomDeFichier := edit2.Text;
MaListe:= TStringList.Create;
If FindFirst(Chemin+ edit3.text,faAnyFile,Info)=0 Then
Repeat
MaListe.Add(Info.Name);
Until FindNext(Info)<>0;
FindClose(Info);
if (MaListe.Count > 0) and
(Application.MessageBox(Pchar('*** Etes vous certain de vouloir renommer ces '+IntToStr(MaListe.Count)+' fichiers ***' ),
'Message ', MB_OKCANCEL) = IDOK) then
try
ProgressBar1.Min := 0;
ProgressBar1.Max := NombreFichiers;
ProgressBar1.Position := 0 ;
IndexFichier:= 1;
for I:= 0 to MaListe.Count -1 do
begin
Fichier := MaListe[I];
MonExtensionDeFichier := ExtractFileExt(Fichier); // on recupere l'extension
FichierRenomme := Chemin + NouveauNomDeFichier + '_0'+ IntToStr(IndexFichier)+ MonExtensionDeFichier;
RenameFile(Chemin + Fichier, FichierRenomme);
Inc(IndexFichier);
end;
ProgressBar1.Position := ProgressBar1.Position +1 ;
Application.MessageBox(Pchar('*** Les '+IntToStr(MaListe.Count)+' fichiers sont renommés avec succès ! ***'), 'Message', MB_OK) ;
except
//....
end;
MaListe.Clear;
MaListe.Free;
end;
Petite remarque : il faudrait ajouter un test pour vérifier que le nouveau nom n'existe pas déjà :
exemple de trois fichiers : 'maison.txt', 'ciel.txt', 'test_02.txt'.
Tu renommes avec le préfixe 'test' : --> 'ciel.txt' devrait se renommer 'test_02.txt' !!!
cincap
Messages postés460Date d'inscriptiondimanche 5 décembre 2004StatutMembreDernière intervention 6 avril 20092 27 janv. 2007 à 07:44
Bonjour,
@ ThWilliam,
Après les différents tests, j'en déduit que cela fonctionne correctement si les fichiers à renommer ne contiennent pas déjà dans le nom une valeur numérique '_01....).
3 fichiers 'maison.txt', 'ciel.txt', 'test.txt'.
Préfixe "test" j'obtiens test_01.txt, test_02.txt et test_03.txt ce qui est le but.
ThWilliam
Messages postés418Date d'inscriptionmardi 3 janvier 2006StatutMembreDernière intervention26 novembre 20134 27 janv. 2007 à 10:39
Salut Cincap,
"j'en déduit que cela fonctionne correctement si les fichiers à renommer ne contiennent pas déjà dans le nom une valeur numérique '_01....)"
Non, ce n'est pas cela la cause.
Ce qui se passe en fait c'est que le 'renommage' s'est opéré chronologiquement ainsi (je pense que ici FindFirst,FindNext renvoie les fichiers triés alphabétiquement : à vérifier) :
- "ciel.txt" est correctement renommé en "test_01.txt"
- "maison.txt" aurait du s'appeler "test_02.txt", mais comme ce nom existe déjà, la fonction RenameFile échoue --> cela reste "maison.txt". Mais, d'après le code, indexfichier s'incrémente, donc passe à 03.
- "test_02.txt" se renomme bien en "test_03.txt"
Au deuxième passage (tjs dans l'ordre alphabétique) :
- "maison.txt" devrait se renommer en "test_01.text", mais ce nom existe déjà, donc pas de renommage et incrémentation de indexfichier à 02.
- "test_01" se renomme bien en "test_02" (ce nom n'existe pas). Indexfichier devient 03.
- "test_03" reste donc "test_03".
RenameFile est une fonction qui renvoie true si le fichier a pu être renommé. Elle ne provoque pas d'exception du genre "erreur: impossible de renommer".
Tu dois absolument avant de renommer un fichier t'assurer que le nouveau nom n'existe déjà pas (sauf si c'est justement le nom original du fichier à renommer). Pour cela, tu a la fonction FileExists. Si cette fonction renvoie true, il faut alors modifier le nouveau nom. Mais il faut de nouveau vérifier si ce nom existe déjà... donc il faut pour chaque fichier faire une boucle avec FileExists jusqu'à trouver un nouveau nom qui n'existe pas. Il y a plusieurs solutions. A toi de voir ce que tu préfères comme nouveau nom.
Remarque : comme ta recherche de fichiers se fait avec attribut 'anyfile', tu prends tous les fichiers y compris les dossiers, fichiers cachés... Si tu veux éviter cela, il faut faire une vérification des attributs du fichier. On peut en reparler...
Les lignes en violet sont juste la pour tester elles sont a remplacer par la ligne en commentaire
// Ici l'on récupère les fichier qui seront renommés
procedure TForm1.FormCreate(Sender: TObject);
Var aDir : String;
begin aDir : = ed_Directory.Text + ed_Extension.Text;
SendMessage(ListBox1.Handle,
LB_DIR, DDL_ARCHIVE + DDL_READWRITE + DDL_EXCLUSIVE, Integer(aDir));
Label1.Caption := IntToStr(ListBox1.Items.Count); // juste pour voir le nombre de fichiers
end ;
// C'est ici que l'on renomme les fichiers
procedure TForm1.Button1Click(Sender: TObject);
Var I : Integer;
Ext, Num : String;
begin ListBox2.Clear; // a supprimer For I : = 0 to ListBox1.Items.Count -1 do Begin Ext := ExtractFileExt(ListBox1.Items[I]);
Num := format('%.3d', [I + 1]); // permet d'obtenir un nombre à trois chiffres Ex. 001
ListBox2.Items.Add(ed_NewName.Text + Num + Ext);// a remplacer par : {MoveFileEx(PChar(ed_Directory.Text + ListBox1.Items[I]),
PChar(ed_Directory.Text + ed_NewName.Text + Num + Ext),
MOVEFILE_COPY_ALLOWED or MOVEFILE_WRITE_THROUGH);} // MoveFileEx te permet de renommer même sur un autre lecteur que le lecteur source
// grace a MOVEFILE_COPY_ALLOWED.
// et MOVEFILE_WRITE_THROUGH rend la main à l'application
// uniquement quand la copie/déplacement est éffectué
End;
end;
// Ici on renomme les fichiers une deuxième fois (juste pour tester) procedure TForm1.Button2Click(Sender: TObject);
Var I : Integer;
Ext, Num : String;
begin ListBox3.Clear;// a supprimer For I : = 0 to ListBox2.Items.Count -1 do Begin Ext := ExtractFileExt(ListBox2.Items[I]);
Num := format('%.3d', [I + 1]);
ListBox3.Items.Add('Teste_' + Num + Ext); // a remplacer par :
{MoveFileEx(PChar(ed_Directory.Text + ListBox2.Items[I]),
PChar(ed_Directory.Text + 'Teste_' + Num + Ext),
MOVEFILE_COPY_ALLOWED or MOVEFILE_WRITE_THROUGH);}
End;
end;
Si tu n'as pas tout compris n'hésite pas à me le dire
cincap
Messages postés460Date d'inscriptiondimanche 5 décembre 2004StatutMembreDernière intervention 6 avril 20092 28 janv. 2007 à 09:37
Bonjour,
@ Cirec, je te remercie de participer à ce post , j'essaye de tester ton code en recréant une nouvelle application et pourtant aucun résultat, rien ne s'affiche dans les listbox.
La question, le dir, l'extension et le new nom doivent se mettre avant la création de la fiche ou après (j'ai testé les deux),
Cela permet de s'assurer que l'on aura assez de chiffres pour le nombre de fichiers.
Ta procedure Button1Click ne résoud pas le problème de 'renommage' avec un nouveau nom existant déjà : dans ce cas, le fichier n'est pas renommé.
ex: 'maison.txt' et 'texte01.txt' : à renommer en 'texte' + 2 chiffres --> si 'maison.txt' est à renommer le premier, il ne sera pas renommé, et 'texte01.txt' deviendra 'texte02.txt'.
J'ai fait un test avec une boucle sur FileExists pour ajouter un chiffre si le fichier existe déjà, mais alors cela donne : 'texte011.txt' et 'texte02.txt'.
Il faudrait une méthode pour ne pas rompre la séquence des chiffres.
Faire un premier passages sur les items de ListBox1 en supprimant de la liste les fichiers qui ont pu être renommés, refaire un passage en partant du dernier nombre... ?
Ou as-tu une autre solution ?
Cirec
Messages postés3833Date d'inscriptionvendredi 23 juillet 2004StatutModérateurDernière intervention18 septembre 202250 28 janv. 2007 à 14:39
ps: j'ai oublié ... en ce qui concerne la numérotation on peut effectivement faire comme le propose ThWilliam
F:= '%.' + IntToStr(Length(IntToStr(ListBox1.Items.Count))) + 'd';
j'avais prévu le coup pour 3 chiffres de 1 à 999 ce qui me semblait suffisant ...
mais on peut aussi tout simplement faire comme ceci (sans calcule supplémentaire) : format('%. 4 d', [I + 1]);
ce qui donne un résultat de 1 à 9999 ... au delà c'est du "suicide"
cincap
Messages postés460Date d'inscriptiondimanche 5 décembre 2004StatutMembreDernière intervention 6 avril 20092 28 janv. 2007 à 23:20
Bonsoir,
C'est vrai que c'est un véritable casse tête, j'ai aussi testé certains logiciels free et shareware et si on refait le test comme ici on obtient un résultat farfelu.
Pour le compteur, de 1 à 999 me semble plus logique.
Quant à la réponse de l'ami Cirec, qui consiste à vérifier si le new name ne se trouve pas dans la liste des fichiers, me semble judicieux.
Le connaissant je suis certain qu'il trouvera une parade à ce problème concernant cette source.
D'ailleurs les sources concernant le renommage des fichiers ont toutes le problème décrit dans ces posts.
Cirec
Messages postés3833Date d'inscriptionvendredi 23 juillet 2004StatutModérateurDernière intervention18 septembre 202250 29 janv. 2007 à 13:45
Juste pour information :
Totale Commander de Christian Ghisler (anciènement WinCommander) dispose d'un outil de renommage par lot très puissant
et lui n'a aucun problème à renommer le cas qui pose problème ici