# Rename multiple files in a directory in Python

## The Question :

407 people think this question is useful

I’m trying to rename some files in a directory using Python.

Say I have a file called CHEESE_CHEESE_TYPE.*** and want to remove CHEESE_ so my resulting filename would be CHEESE_TYPE

I’m trying to use the os.path.split but it’s not working properly. I have also considered using string manipulations, but have not been successful with that either.

• Your needle is not in the haystack, your haystack has a wildcard, and even ignoring case your result cannot come from that haystack. Care to clean up the question a bit?
• Ok, I’ll try to clear it up as best I can. I have a folder of files that all are named something like cheese_cheese_type.prj (all have the same first 15 chars, but different trailing 4 chars & extensions) Im trying to remove the first 8 charecters from the filename (in the example, ‘cheese_’ would be removed and the resulting filename would be cheese_type.prj so what Im trying to do is walk the directory, split the file names, and remove the first 8 characters from the filename. in would be cheese_cheese_type.prj out would be cheese_type.prj Thanks!

642 people think this answer is useful

Use os.rename(src, dst) to rename or move a file or a directory.

$ls cheese_cheese_type.bar cheese_cheese_type.foo$ python
>>> import os
>>> for filename in os.listdir("."):
...  if filename.startswith("cheese_"):
...    os.rename(filename, filename[7:])
...
>>>
$ls cheese_type.bar cheese_type.foo  ## The Answer 2 38 people think this answer is useful Here’s a script based on your newest comment. #!/usr/bin/env python from os import rename, listdir badprefix = "cheese_" fnames = listdir('.') for fname in fnames: if fname.startswith(badprefix*2): rename(fname, fname.replace(badprefix, '', 1))  ## The Answer 3 23 people think this answer is useful The following code should work. It takes every filename in the current directory, if the filename contains the pattern CHEESE_CHEESE_ then it is renamed. If not nothing is done to the filename. import os for fileName in os.listdir("."): os.rename(fileName, fileName.replace("CHEESE_CHEESE_", "CHEESE_"))  ## The Answer 4 15 people think this answer is useful Assuming you are already in the directory, and that the “first 8 characters” from your comment hold true always. (Although “CHEESE_” is 7 characters… ? If so, change the 8 below to 7) from glob import glob from os import rename for fname in glob('*.prj'): rename(fname, fname[8:])  ## The Answer 5 11 people think this answer is useful I have the same issue, where I want to replace the white space in any pdf file to a dash -. But the files were in multiple sub-directories. So, I had to use os.walk(). In your case for multiple sub-directories, it could be something like this: import os for dpath, dnames, fnames in os.walk('/path/to/directory'): for f in fnames: os.chdir(dpath) if f.startswith('cheese_'): os.rename(f, f.replace('cheese_', ''))  ## The Answer 6 7 people think this answer is useful Try this: import os import shutil for file in os.listdir(dirpath): newfile = os.path.join(dirpath, file.split("_",1)[1]) shutil.move(os.path.join(dirpath,file),newfile)  I’m assuming you don’t want to remove the file extension, but you can just do the same split with periods. ## The Answer 7 6 people think this answer is useful This sort of stuff is perfectly fitted for IPython, which has shell integration. In [1] files = !ls In [2] for f in files: newname = process_filename(f) mv$f $newname  Note: to store this in a script, use the .ipy extension, and prefix all shell commands with !. ## The Answer 8 5 people think this answer is useful Here is a more general solution: This code can be used to remove any particular character or set of characters recursively from all filenames within a directory and replace them with any other character, set of characters or no character. import os paths = (os.path.join(root, filename) for root, _, filenames in os.walk('C:\FolderName') for filename in filenames) for path in paths: # the '#' in the example below will be replaced by the '-' in the filenames in the directory newname = path.replace('#', '-') if newname != path: os.rename(path, newname)  ## The Answer 9 4 people think this answer is useful It seems that your problem is more in determining the new file name rather than the rename itself (for which you could use the os.rename method). It is not clear from your question what the pattern is that you want to be renaming. There is nothing wrong with string manipulation. A regular expression may be what you need here. ## The Answer 10 4 people think this answer is useful This command will remove the initial “CHEESE_” string from all the files in the current directory, using renamer: $ renamer --find "/^CHEESE_/" *



3 people think this answer is useful

I was originally looking for some GUI which would allow renaming using regular expressions and which had a preview of the result before applying changes.

On Linux I have successfully used krename, on Windows Total Commander does renaming with regexes, but I found no decent free equivalent for OSX, so I ended up writing a python script which works recursively and by default only prints the new file names without making any changes. Add the ‘-w’ switch to actually modify the file names.

#!/usr/bin/python
# -*- coding: utf-8 -*-

import os
import fnmatch
import sys
import shutil
import re

def usage():
print """
Usage:
%s <work_dir> <search_regex> <replace_regex> [-w|--write]

By default no changes are made, add '-w' or '--write' as last arg to actually rename files
after you have previewed the result.
""" % (os.path.basename(sys.argv[0]))

def rename_files(directory, search_pattern, replace_pattern, write_changes=False):

pattern_old = re.compile(search_pattern)

for path, dirs, files in os.walk(os.path.abspath(directory)):

for filename in fnmatch.filter(files, "*.*"):

if pattern_old.findall(filename):
new_name = pattern_old.sub(replace_pattern, filename)

filepath_old = os.path.join(path, filename)
filepath_new = os.path.join(path, new_name)

if not filepath_new:
print 'Replacement regex {} returns empty value! Skipping'.format(replace_pattern)
continue

print new_name

if write_changes:
shutil.move(filepath_old, filepath_new)
else:
print 'Name [{}] does not match search regex [{}]'.format(filename, search_pattern)

if __name__ == '__main__':
if len(sys.argv) < 4:
usage()
sys.exit(-1)

work_dir = sys.argv[1]
search_regex = sys.argv[2]
replace_regex = sys.argv[3]
write_changes = (len(sys.argv) > 4) and sys.argv[4].lower() in ['--write', '-w']
rename_files(work_dir, search_regex, replace_regex, write_changes)



### Example use case

I want to flip parts of a file name in the following manner, i.e. move the bit m7-08 to the beginning of the file name:

# Before:
Summary-building-mobile-apps-ionic-framework-angularjs-m7-08.mp4

# After:
m7-08_Summary-building-mobile-apps-ionic-framework-angularjs.mp4



This will perform a dry run, and print the new file names without actually renaming any files:

rename_files_regex.py . "([^\.]+?)-(m\\d+-\\d+)" "\\2_\\1"



This will do the actual renaming (you can use either -w or --write):

rename_files_regex.py . "([^\.]+?)-(m\\d+-\\d+)" "\\2_\\1" --write



3 people think this answer is useful

import os import string def rename_files():

#List all files in the directory
file_list = os.listdir("/Users/tedfuller/Desktop/prank/")
print(file_list)

#Change current working directory and print out it's location
working_location = os.chdir("/Users/tedfuller/Desktop/prank/")
working_location = os.getcwd()
print(working_location)

#Rename all the files in that directory
for file_name in file_list:
os.rename(file_name, file_name.translate(str.maketrans("","",string.digits)))



rename_files()

2 people think this answer is useful

You can use os.system function for simplicity and to invoke bash to accomplish the task:

import os
os.system('mv old_filename new_filename')



0 people think this answer is useful

import re
p = re.compile(r'_')
p.split(filename, 1) #where filename is CHEESE_CHEESE_TYPE.***



import os