View Issue Details

IDProjectCategoryView StatusLast Update
0002267Double CommanderFile operationspublic2021-10-29 23:21
ReporterCryHam Assigned ToAlexx2000  
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
ProjectionnoneETAnone 
Product Version1.0.0 (trunk)Product Buildr8738 
Fixed in Version1.0.0 
Summary0002267: [Patch] Multi Rename - Avoid collisions with OldFiles
DescriptionSo TC handles multi renames even if new names collide.
E.g. if old files names are 001 to 005 and new names 004 to 008, then renaming 001 to 004 would overwrite already existing file 004.

I'm not sure how TC does it, but I did it in DC like so:
1. Added TStringHashList OldNames and filled with all OldFiles.
2. Before adding to rename operation I check if new name exists in OldNames, if so then I'm adding a @ at end of file name, before extension (if any). So first there will be 004@ and 005@ files.
3. Then after operation finishes, I'm iterating all again and (again checking) then renaming them back, removing @ char from name.

The code in patch works, but surely is far from great.
I tried before to use that TFileSourceOperation, but it complained that it can't rename 004@ to 004 back, etc. IDK why. Then I tried duplicating that code, to have second operation after the first finished, but this way also had the same issue.
Also I guess, points 2 and 3 could probably be coded to execute faster.
TagsNo tags attached.
Attached Files
fmultirename.pas.patch (2,146 bytes)   
Index: fmultirename.pas
===================================================================
--- fmultirename.pas	(revision 8738)
+++ fmultirename.pas	(working copy)
@@ -996,10 +996,11 @@
 
 procedure TfrmMultiRename.RenameFiles;
 var
-  AFile: TFile;
+  AFile,OFile: TFile;
   NewName: String;
-  I, J, K: Integer;
+  I, J, K, L: Integer;
   OldFiles, NewFiles: TFiles;
+  OldNames: TStringHashList;
   AutoRename: Boolean = False;
   Operation: TFileSourceOperation;
   theNewProperties: TFileProperties;
@@ -1016,11 +1017,29 @@
   NewFiles:= TFiles.Create(EmptyStr);
 
   try
+    // OldNames
+    OldNames:= TStringHashList.Create(True);
+    OldNames.Clear;
+    for I:= 0 to OldFiles.Count -1 do
+      OldNames.Add(OldFiles[I].Name);
+
     FNewNames.Clear;
     for I:= 0 to FFiles.Count - 1 do
     begin
       AFile:= TFile.Create(EmptyStr);
       AFile.Name:= FreshText(I);
+
+      // Avoid collisions with OldNames
+      L:= OldNames.Find(AFile.Name);
+      if L >= 0 then
+      begin
+        // Add @ at end of name
+        if AFile.Extension = '' then
+          AFile.Name:= AFile.NameNoExt + '@'
+        else
+          AFile.Name:= AFile.NameNoExt + '@.' + AFile.Extension;
+      end;
+
       // Checking duplicates
       NewName:= FFiles[I].Path + AFile.Name;
       J:= FNewNames.Find(NewName);
@@ -1073,6 +1092,30 @@
     NewFiles.Free;
   end;
 
+  // Rename files back, remove @
+  for I:= 0 to FFiles.Count - 1 do
+  begin
+    AFile:= TFile.Create(EmptyStr);
+    AFile.Name:= FreshText(I);
+    OFile:= AFile.Clone;
+
+    L:= OldNames.Find(AFile.Name);
+    if L >= 0 then
+    begin
+      if AFile.Extension = '' then
+      begin
+        OFile.Name:= FFiles[I].Path + AFile.NameNoExt + '@';
+        RenameFile(FFileSource, OFile, AFile.NameNoExt, True);
+      end else begin
+        OFile.Name:= FFiles[I].Path + AFile.NameNoExt + '@.' + AFile.Extension;
+        RenameFile(FFileSource, OFile, AFile.NameNoExt + '.' + AFile.Extension, True);
+      end;
+      FFiles[I].Name := AFile.Name;
+    end;
+    AFile.Free;
+    OFile.Free;
+  end;
+
   StringGridTopLeftChanged(StringGrid);
 end;
 
fmultirename.pas.patch (2,146 bytes)   
Fixed in Revision8850, 8852
Operating systemWindows
WidgetsetWin32
Architecture64-bit

Relationships

related to 0002054 closedAlexx2000 Multi Rename Tool not working for "repeating" filenames 

Activities

CryHam

2019-03-19 02:23

reporter   ~0003104

Last edited: 2019-03-19 02:24

Patch is on svn revision 8738. I tested only on Windows.
And I didn't test log to file (doesn't work) or for any file access errors during renaming in point 3.
Lastly I assumed that there won't be any same files with that @ symbol at end already existing.

Alexx2000

2019-05-19 21:03

administrator   ~0003163

I made alternative implementation.

Issue History

Date Modified Username Field Change
2019-03-19 02:19 CryHam New Issue
2019-03-19 02:19 CryHam File Added: fmultirename.pas.patch
2019-03-19 02:23 CryHam Note Added: 0003104
2019-03-19 02:24 CryHam Note Edited: 0003104
2019-05-19 21:03 Alexx2000 Fixed in Revision => 8850
2019-05-19 21:03 Alexx2000 Note Added: 0003163
2019-05-19 21:03 Alexx2000 Status new => resolved
2019-05-19 21:03 Alexx2000 Fixed in Version => 1.0.0
2019-05-19 21:03 Alexx2000 Resolution open => fixed
2019-05-19 21:03 Alexx2000 Assigned To => Alexx2000
2019-05-19 21:06 Alexx2000 Relationship added related to 0002054
2019-05-21 21:00 Alexx2000 Fixed in Revision 8850 => 8850, 8852
2021-10-29 23:21 Alexx2000 Status resolved => closed