sorting for recursive folder rename

Peter Otten __peter__ at web.de
Fri Feb 6 13:02:12 CET 2009


ianaré wrote:

> On Dec 16 2008, 7:36 pm, "Rhodri James" <rho... at wildebst.demon.co.uk>
> wrote:
>> On Tue, 16 Dec 2008 18:20:52 -0000, ianaré <ian... at gmail.com> wrote:
>> > Hello all,
>>
>> > I trying to recursivelyrenamefolders and files, and am looking for
>> > some ideas on the best way of doing this. The problem is that the
>> > given list of items can be in order, and one to all items may be
>> > renamed. Here is some preliminary code I have, but which does not work
>> > very well.
> 
> self.toRename has the following structure :
> [
> [original_name, new_name, os.path.isdir]
> ..
> ]
> 
> # define these here for faster processing
> def split(item):
>     return os.path.split(item)
> def addSep(path):
>     return os.sep + path + os.sep
> def recursiveFolderSort(x,y):
>     return cmp(y[0], x[0])
> 
> sortedRename = sorted(self.toRename)
> 
> # make a list of all folders that will be processed
> foldersToAdjust = []
> for item in sortedRename:
>     if item[2] is False:
>         oF = split(item[0])[1] # original folder name
>         nF = split(item[1])[1] # new folder name
>         if oF is not nF:
>             foldersToAdjust.append((oF, nF))
> 
> # replace all occurences of folders in path
> for i in range(len(self.toRename)):
>     for f in foldersToAdjust:
>         oF = addSep(f[0]) # original folder name
>         nF = addSep(f[1]) # new folder name
>         self.toRename[i][0] = self.toRename[i][0].replace(oF,nF)
>         self.toRename[i][1] = self.toRename[i][1].replace(oF,nF)
> 
>     if progressDialog.update(i) is False:
>         error = 'cancelled'
>         break
> 
> # make sure renaming will be in correct order !
> self.toRename.sort(recursiveFolderSort)
> 
>> import os
>>
>> for item in self.toRename:
>> os.renames(item[0], item[1])
>>
>> That's it.  os.renames will take care of all the intermediate
>> directory creation so you don't even need to sort the list.
>>
>> --
>> Rhodri James *-* Wildebeeste Herder to the Masses
> 
> It's been a while since I decided to work on this again ...
> 
> Anyway, if only it were that easy !!
> 
> Traceback (most recent call last):
>   File "/home/ianare/Desktop/file-folder-ren/metamorphose2/Source/
> MainWindow.py", line 1477, in renameItems
>     os.renames(original[0], renamed[0])
>   File "/usr/lib/python2.5/os.py", line 213, in renames
>     rename(old, new)
> OSError: [Errno 2] No such file or directory
> 
> 
> The problem is that if a directory is changed, all lower instances
> need to be changed as well.
> 
> given the following directory structure ...
> 
> recursive
> |
> |_1
> |  |_1
> |  |  |_1.txt
> |  |  |_2.txt
> |  |_2
> |     |_1.txt
> |     |_2.txt
> |_2
>    |_1
>    |  |_1.txt
>    |  |_2.txt
>    |_2
>       |_1.txt
>       |_2.txt
> 
> ... and assuming I want to change :
> recursive/2/2/2.txt  -->  recursive/2/2/14.txt
> 
> but, I ALSO want to change :
> recursive/2  -->  recursive/04
> 
> it means that the first operation is really :
> recursive/04/2/2.txt  -->  recursive/04/2/14.txt
> 
> os.renames will work, but it needs to have the correct path, so it
> comes down to the same thing.
> 
> IOW, I need a way of :
> A) adjusting paths taking into consideration all changes up and down
> the tree
> B) sorting normalized paths so they are renamed in the proper sequence
> (depends on point 'A', obviously)
> 
> I'm pretty sure I can take care of 'B' with the following sorting
> method:
> 
> # order by path depth
> def recursiveFolderSort(x, y):
>     x = x[0].count(os.sep)
>     y = y[0].count(os.sep)
>     return cmp(x, y)
> self.toRename.sort(recursiveFolderSort)
> 
> but I still need a way of generating the correct names.


I don't see the problem. Just rename the deepest files and directories
first.

# untested

def old_depth((old, new)):
    p = os.path.abspath(old)
    return p.count(os.sep) - p.endswith(os.sep) # don't count trailing slash

pairs = sorted(self.toRename, key=old_depth, reverse=True)
for old, new in pairs:
   os.rename(old, new)

Because "recursive/2/2/2.txt" has more slashes it will be processed
before "recursive/2" and thus when the latter is processed the former's
path will change implicitly.

Peter



More information about the Python-list mailing list