Python Forum

Full Version: Rename part of filename in multiple files
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hello, I'm trying to replace part of a text in a filename for multiple files. But it is not working. Your help is greatly appreciated.

Example:

my document 2022XX_reference.docx
my document 2022XX_manual.docx
my document 2022XX_manual.pdf

Output:
Output: my document 202205_reference.docx my document 202205_manual.docx my document 202205_manual.pdf
import os
counter = 0
path = r"C:\files\documents"

files = [] 
for file in os.listdir(path):
    if file.endswith(".*"):
        if file.find("XX") > -1:
            counter = counter + 1
            newFileName = file.replace("XX", "05")
            files.append((file, newFileName))
Try this and let us know if it's what you were looking for.
import os
counter = 0
path = r"C:\files\documents"
files = [] 
for file_name in os.listdir (path):
	if "XX" in file_name :
		old_name = file_name
		new_name = file_name.replace ("XX", "05")
		counter += 1
		files.append (new_name)
		os.rename (old_name, new_name)
print (counter)
print (files)
What should the counter count? The amount of matching/renamed files or the amount of all files?

Try not to use os.path.*
The module pathlib gives a nice high-level abstraction of Paths.
If you use it right, your code could also work on different operating systems with different directory structure.

For example Windows Users home is in: C:\Users
For linux it's in /home

The class method pathlib.Path.home() returns a Path object, which points to your current home directory independent of your OS that you're using. On Windows, you get back a WindowsPath which points to C:\Users\username and on Linux you get a PosixPath which points to /home/username. Mac should be the same as Linux.

You can do this also with os.path, but this is very low level.

from pathlib import Path


for source_file in Path.home().joinpath("Dokumente").glob("*.xlsx"):
    # in my case the user is andre
    # resulting Path:
    # /home/andre/Deokumente
    # the method glob will yield files and directories
    # which matches the pattern *.xlsx
    # glob only searches one level deep
    # rglob searchs recursive
    # iterdir does not pattern matching and just yields
    # the paths (files and other) in the directory

    # process only files, keep in mind, that you can
    # also have a directory names like something.xlsx

    if source_file.is_file():
        print("OLD:", source_file)
        # the attribute name of a Path object is a str
        # creating a new name with replace
        new_name = source_file.name.replace("XX", "05")
        # now we need the full path to the target file
        # the method with_name replaces the last part of
        # a Path object
        target_file = source_file.with_name(new_name)
        print("NEW:", target_file)

        # Path objects can also: rename, unlink, chmod, stat, open, read_text, ...
        # to rename them:
        # source_file.rename(source_file)
If the counter is needed, you can use enumerate to count all matching files:
path_iterator = Path.home().joinpath("Dokumente").glob("*.xlsx")

for file_count, source_file in enumerate(path_iterator, start=1):
    ...
Then you can use file_count in the for-loop if required and even after the for-loop has been finished, the file_count and source_file do have the last elements.
They are not removed.

Example:
for number in range(10):
    pass # doing nothing


# -> 9, the last value of the for-loop
print(number)
(Feb-17-2022, 01:21 AM)BashBedlam Wrote: [ -> ]Try this and let us know if it's what you were looking for.
import os
counter = 0
path = r"C:\files\documents"
files = [] 
for file_name in os.listdir (path):
	if "XX" in file_name :
		old_name = file_name
		new_name = file_name.replace ("XX", "05")
		counter += 1
		files.append (new_name)
		os.rename (old_name, new_name)
print (counter)
print (files)

Hi, thank you the response and it works! awesome!

at first, i tried the files from different folder that's why i got an error like

Error:
Exception has occurred: FileNotFoundError [WinError 2] The system cannot find the file specified: 'my document 2022XX_manual.docx' -> 'my document 202205_manual.docx'
but the Solution is place the files required and script in same folder.
(Feb-17-2022, 06:30 PM)atomxkai Wrote: [ -> ]but the Solution is place the files required and script in same folder.
os.listdir(path) only returns the files names,and not the absolute paths.
Can add this to line 5,and it should work.
os.chdir(path)
Or use Pathlib as shown which return absolute paths.
(Feb-17-2022, 06:30 PM)atomxkai Wrote: [ -> ]Hi, thank you the response and it works! awesome!
Always happy to help Smile
(Feb-17-2022, 12:07 PM)DeaD_EyE Wrote: [ -> ]What should the counter count? The amount of matching/renamed files or the amount of all files?

Try not to use os.path.*
The module pathlib gives a nice high-level abstraction of Paths.
If you use it right, your code could also work on different operating systems with different directory structure.

For example Windows Users home is in: C:\Users
For linux it's in /home

The class method pathlib.Path.home() returns a Path object, which points to your current home directory independent of your OS that you're using. On Windows, you get back a WindowsPath which points to C:\Users\username and on Linux you get a PosixPath which points to /home/username. Mac should be the same as Linux.

Thank you so much for the detailed response. I will try to learn your script, i think i'm still in the stage of figuring out the function and its syntax.

For the counter, is just for how many files will be renamed.
(Feb-17-2022, 06:48 PM)snippsat Wrote: [ -> ]
(Feb-17-2022, 06:30 PM)atomxkai Wrote: [ -> ]but the Solution is place the files required and script in same folder.
os.listdir(path) only returns the files names,and not the absolute paths.
Can add this to line 5,and it should work.
os.chdir(path)
Or use Pathlib as shown which return absolute paths.

Thank you for this.