Reputation: 65
I am trying to rename multiple mp3 files I have in a folder. They start with something like "1 Hotel California - The Eagles" and so on. I would like it to be just "Hotel California - The Eagles". Also, there could be a "05 Hotel California - The Eagles" as well, which means removing the number from a different files would create duplicates, which is the problem I am facing. I want it to replace existing files/overwrite/delete one of them or whatever a solution might be. P.S, Adding "3" to the "1234567890 " would remove the "3" from the .mp3 extension
I am new to python, but here is the code I am using to implement this
import os
def renamefiles():
list = os.listdir(r"E:\NEW")
print(list)
path = os.getcwd()
print(path)
os.chdir(r"E:\NEW")
for name in list:
os.rename(name, name.translate(None, "124567890 "))
os.chdir(path)
renamefiles()
And here is the error I get WindowsError: [Error 183] Cannot create a file when that file already exists
Any help on how I could rename the files correctly would be highly appreciated!
Upvotes: 2
Views: 5608
Reputation: 312
You just need to change directory to where *.mp3 files are located and execute 2 lines of below with python:
import os,re
for filename in os.listdir():
os.rename(filename, filname.strip(re.search("[0-9]{2}", filename).group(0)))
Upvotes: 0
Reputation: 1500
I was unable to easily get any of the answers to work with Python 3.5, so here's one that works under that condition:
import os
import re
def rename_files():
path = os.getcwd()
file_names = os.listdir(path)
for name in file_names:
os.rename(name, re.sub("[0-9](?!\d*$)", "", name))
rename_files()
This should work for a list of files like "1 Hotel California - The Eagles.mp3", renaming them to "Hotel California - The Eagles.mp3" (so the extension is untouched).
Upvotes: 2
Reputation: 77902
Ok so what you want is:
The following code should work (not tested).
import os
import string
class FileExists(Exception):
pass
def rename_files(path, ext, remove_existing=True):
for fname in os.listdir(path):
# test if the file name ends with the expected
# extension else skip it
if not fname.endswith(ext):
continue
# chdir is not a good idea, better to work
# with absolute path whenever possible
oldpath = os.path.join(path, fname)
# remove _leading_ digits then remove all whitespaces
newname = fname.lstrip(string.digits).strip()
newpath = os.path.join(path, newname)
# check if the file already exists
if os.path.exists(newpath):
if remove_existing:
# it exists and we were told to
# remove existing file:
os.remove(newpath)
else:
# it exists and we were told to
# NOT remove existing file:
raise FileExists(newpath)
# ok now we should be safe
os.rename(oldpath, newpath)
# only execute the function if we are called directly
# we dont want to do anything if we are just imported
# from the Python shell or another script or module
if __name__ == "__main__":
# exercice left to the reader:
# add command line options / arguments handling
# to specify the path to browse, the target
# extension and whether to remove existing files
# or not
rename_files(r"E:\NEW", ".mp3", True)
Upvotes: 0
Reputation: 180401
You can catch an OSError
and also use glob
to find the .mp3 files:
import os
from glob import iglob
def renamefiles(pth):
os.chdir(pth)
for name in iglob("*.mp3"):
try:
os.rename(name, name.translate(None, "124567890").lstrip())
except OSError:
print("Caught error for {}".format(name))
# os.remove(name) ?
What you do when you catch the error is up to you, you could keep some record of names found and increment a count for each or leave as is.
If the numbers are always at the start you can also just lstrip then away so you can then use 3 safely:
os.rename(name, name.lstrip("0123456789 "))
using one of your example strings:
In [2]: "05 Hotel California - The Eagles.mp3".lstrip("01234567890 ")
Out[2]: 'Hotel California - The Eagles.mp3'
Using your original approach could never work as desired as you would remove all spaces:
In [3]: "05 Hotel California - The Eagles.mp3".translate(None,"0124567890 ")
Out[3]: 'HotelCalifornia-TheEagles.mp3'
If you don't care what file gets overwritten you can use shutil.move
:
import os
from glob import iglob
from shutil import move
def renamefiles(pth):
os.chdir(pth)
for name in iglob("*.mp3"):
move(name, name.translate(None, "124567890").lstrip())
On another note, don't use list
as a variable name.
Upvotes: 2
Reputation: 5515
instead of using name.translate, import the re lib (regular expressions) and use something like
"(?:\d*)?\s*(.+?).mp3"
as your pattern. You can then use
Match.group(1)
as your rename.
For dealing with multiple files, add an if statement that checks if the file already exists in the library like this:
os.path.exists(dirpath)
where dirpath is the directory that you want to check in
Upvotes: 2
Reputation: 155363
You need to verify that the names being changed actually changed. If the name doesn't have digits or spaces in it, the translate
will return the same string, and you'll try to rename name
to name
, which Windows rejects. Try:
for name in list:
newname = name.translate(None, "124567890 ")
if name != newname:
os.rename(name, newname)
Note, this will still fail if the file target exists, which you'd probably want if you were accidentally collapsing two names into one. But if you want silent replace behavior, if you're on Python 3.3 or higher, you can change os.rename
to os.replace
to silently overwrite; on earlier Python, you can explicitly os.remove
before calling os.rename
.
Upvotes: 4