Denver Dang
Denver Dang

Reputation: 2605

Rename multiple files inside multiple folders

So I have a lot of folders with a certain name. In each folder I have +200 items. The items inside the folders has names like:

CT.34562346.246.dcm
RD.34562346.dcm
RN.34562346.LAO.dcm

And some along that style.

I now wish to rename all files inside all folders so that the number (34562346) is replaced with the name of the folder. So for example in the folder named "1" the files inside should become:

CT.1.246.dcm
RD.1.dcm
RN.1.LAO.dcm

So only the large number is replaced. And yes, all files are similar like this. It would be the number after the first . that should be renamed.

So far I have:

import os

base_dir = "foo/bar/"    #In this dir I have all my folders

dir_list = []
for dirname in os.walk(base_dir):
    dir_list.append(dirname[0])

This one just lists the entire paths of all folders.

dir_list_split = []
for name in dir_list[1:]:   #The 1 is because it lists the base_dir as well
    x = name.split('/')[2]
    dir_list_split.append(x)

This one extracts the name of each folder.

And then the next thing would be to enter the folders and rename them. And I'm kind of stuck here ?

Upvotes: 1

Views: 2605

Answers (3)

Bill Bell
Bill Bell

Reputation: 21663

The pathlib module, which was new in Python 3.4, is often overlooked. I find that it often makes code simpler than it would otherwise be with os.walk.

In this case, .glob('**/*.*') looks recursively through all of the folders and subfolders that I created in a sample folder called example. The *.* part means that it considers all files.

I put path.parts in the loop to show you that pathlib arranges to parse pathnames for you.

I check that the string constant '34562346' is in its correct position in each filename first. If it is then I simply replace it with the items from .parts that is the next level of folder 'up' the folders tree.

Then I can replace the rightmost element of .parts with the newly altered filename to create the new pathname and then do the rename. In each case I display the new pathname, if it was appropriate to create one.

>>> from pathlib import Path
>>> from os import rename
>>> for path in Path('example').glob('**/*.*'):
...     path.parts
...     if path.parts[-1][3:11]=='34562346':
...         new_name = path.parts[-1].replace('34562346', path.parts[-2])
...         new_path = '/'.join(list(path.parts[:-1])+[new_name])
...         new_path
...         ## rename(str(path), new_path)
...     else:
...         'no change'
... 
('example', 'folder_1', 'id.34562346.6.a.txt')
'example/folder_1/id.folder_1.6.a.txt'
('example', 'folder_1', 'id.34562346.wax.txt')
'example/folder_1/id.folder_1.wax.txt'
('example', 'folder_2', 'subfolder_1', 'ty.34562346.90.py')
'example/folder_2/subfolder_1/ty.subfolder_1.90.py'
('example', 'folder_2', 'subfolder_1', 'tz.34562346.98.py')
'example/folder_2/subfolder_1/tz.subfolder_1.98.py'
('example', 'folder_2', 'subfolder_2', 'doc.34.34562346.implication.rtf')
'no change'

Upvotes: 2

0liveradam8
0liveradam8

Reputation: 778

This will rename files in subdirectories too:

import os
rootdir = "foo" + os.sep + "bar"
for subdir, dirs, files in os.walk(rootdir):
    for file in files:
        filepath = subdir + os.sep + file
        foldername = subdir.split(os.sep)[-1]

        number = ""
        foundnumber = False

        for c in filepath:
            if c.isdigit():
                foundnumber = True
                number = number + c
            elif foundnumber:
                break
        if foundnumber:
            newfilepath = filepath.replace(number,foldername)
            os.rename(filepath, newfilepath)

Upvotes: 2

Chris
Chris

Reputation: 16172

Split each file name on the . and replace the second item with the file name, then join on .'s again for the new file name. Here's some sample code that demonstrates the concept.

folder_name = ['1', '2']

file_names = ['CT.2345.234.dcm', 'BG.234234.222.dcm', "RA.3342.221.dcm"]


for folder in folder_name:
    new_names = []
    for x in file_names:
        file_name = x.split('.')
        file_name[1] = folder
        back_together = '.'.join(file_name)
        new_names.append(back_together)

    print(new_names)

Output

['CT.1.234.dcm', 'BG.1.222.dcm', 'RA.1.221.dcm']
['CT.2.234.dcm', 'BG.2.222.dcm', 'RA.2.221.dcm']

Upvotes: 0

Related Questions