How do i rename a bunch of files with a list from a text file in Python?

Viewed 447

I'm starting learning Python, I'm doing a project that renames a bunch of files from a list of the text files that contains the new names of the files.

In my folder I have files like lesson1.mp4, lesson2.mp4, lesson3.mp4 ... and so on. And in the text file, I have the new names 1-newname, 2-newname, 3-newname (separated by a newline).

First, I change the directory and store the variable in file and then I use file.readlines() to separate line by line.

import os

os.chdir(r"C:\Users\Samaritan\Documents\Python\
Ejercicios\pruebarenamefiles")

file = open('new_names.txt')
lines = file.readlines()

Then, I created a function to return the new names based on the position of the list.

def n_name(num):     
    return lines[num]

Then I iterate over the directory and rename each position with the function n_name

i = 0
for file in os.listdir():
    if file != "new_names.txt":
        os.rename(file, n_name(i))
        i += 1

But it doesn't work at all. I got "OSError: [WinError 123]"

C:\Users\Samaritan\Documents\Python\Ejercicios\rename_files\venv\Scripts\python.exe C:/Users/Samaritan/Documents/Python/Ejercicios/rename_files/main.py
Traceback (most recent call last):

File "C:\Users\Samaritan\Documents\Python\Ejercicios\rename_files\main.py", line 16, in <module>
    os.rename(file, n_name(i)) OSError: [WinError 123] El nombre de archivo, el nombre de directorio o la sintaxis de la etiqueta del volumen no son correctos: 'Nuevo documento de texto - copia (2).txt'
-> '01 - Course Introduction\n'

Process finished with exit code 1

In English it means something like this: WindowsError: [Error 123] The filename, directory name, or volume label syntax is incorrect:

1 Answers

The error message indicates the problem if you read it carefully. The destination file name contains a newline character at the end, which isn't allowed on Windows.

To read the lines without newlines, try

with open("new_names.txt") as file:
    lines = [line.rstrip("\n") for line in file]

However, it's also weird to use a separate function to obtain the n:th object out of a list; indexing is a fundamental built-in method of lists.

files = os.listdir()
files.remove("new_names.txt")
for idx, filename in enumerate(files):
    os.rename(filename, lines[idx])

Identically, you could zip the two lists, as suggested in the other answer, but then you still separately have to remove new_names.txt from the input list first, like the code above does.

If the new names are as monotonous as your question suggests, maybe just generate them on the fly instead of putting them in a file.

idx = 1
for filename in os.listdir():
    if file == "new_names.txt":
        continue
    os.rename(filename, f"{idx}-newname.txt")
    idx += 1

If you want to apply formatting to the number, try e.g. f"{idx:02}-newname.txt" to force the index number to two digits with zero padding.

Related