Batch Renaming of Files in a Directory

Question:

Is there an easy way to rename a group of files already contained in a directory, using Python?

Example: I have a directory full of *.doc files and I want to rename them in a consistent way.

X.doc -> “new(X).doc”

Y.doc -> “new(Y).doc”

Asked By: Nate

||

Answers:

Try: http://www.mattweber.org/2007/03/04/python-script-renamepy/

I like to have my music, movie, and
picture files named a certain way.
When I download files from the
internet, they usually don’t follow my
naming convention. I found myself
manually renaming each file to fit my
style. This got old realy fast, so I
decided to write a program to do it
for me.

This program can convert the filename
to all lowercase, replace strings in
the filename with whatever you want,
and trim any number of characters from
the front or back of the filename.

The program’s source code is also available.

Answered By: xsl

Such renaming is quite easy, for example with os and glob modules:

import glob, os

def rename(dir, pattern, titlePattern):
    for pathAndFilename in glob.iglob(os.path.join(dir, pattern)):
        title, ext = os.path.splitext(os.path.basename(pathAndFilename))
        os.rename(pathAndFilename, 
                  os.path.join(dir, titlePattern % title + ext))

You could then use it in your example like this:

rename(r'c:tempxx', r'*.doc', r'new(%s)')

The above example will convert all *.doc files in c:tempxx dir to new(%s).doc, where %s is the previous base name of the file (without extension).

Answered By: DzinX

If you don’t mind using regular expressions, then this function would give you much power in renaming files:

import re, glob, os

def renamer(files, pattern, replacement):
    for pathname in glob.glob(files):
        basename= os.path.basename(pathname)
        new_filename= re.sub(pattern, replacement, basename)
        if new_filename != basename:
            os.rename(
              pathname,
              os.path.join(os.path.dirname(pathname), new_filename))

So in your example, you could do (assuming it’s the current directory where the files are):

renamer("*.doc", r"^(.*).doc$", r"new(1).doc")

but you could also roll back to the initial filenames:

renamer("*.doc", r"^new((.*)).doc", r"1.doc")

and more.

Answered By: tzot

I prefer writing small one liners for each replace I have to do instead of making a more generic and complex code. E.g.:

This replaces all underscores with hyphens in any non-hidden file in the current directory

import os
[os.rename(f, f.replace('_', '-')) for f in os.listdir('.') if not f.startswith('.')]
Answered By: Cesar Canassa

I’ve written a python script on my own. It takes as arguments the path of the directory in which the files are present and the naming pattern that you want to use. However, it renames by attaching an incremental number (1, 2, 3 and so on) to the naming pattern you give.

import os
import sys

# checking whether path and filename are given.
if len(sys.argv) != 3:
    print "Usage : python rename.py <path> <new_name.extension>"
    sys.exit()

# splitting name and extension.
name = sys.argv[2].split('.')
if len(name) < 2:
    name.append('')
else:
    name[1] = ".%s" %name[1]

# to name starting from 1 to number_of_files.
count = 1

# creating a new folder in which the renamed files will be stored.
s = "%s/pic_folder" % sys.argv[1]
try:
    os.mkdir(s)
except OSError:
    # if pic_folder is already present, use it.
    pass

try:
    for x in os.walk(sys.argv[1]):
        for y in x[2]:
            # creating the rename pattern.
            s = "%spic_folder/%s%s%s" %(x[0], name[0], count, name[1])
            # getting the original path of the file to be renamed.
            z = os.path.join(x[0],y)
            # renaming.
            os.rename(z, s)
            # incrementing the count.
            count = count + 1
except OSError:
    pass

Hope this works for you.

Answered By: harisibrahimkv

I have this to simply rename all files in subfolders of folder

import os

def replace(fpath, old_str, new_str):
    for path, subdirs, files in os.walk(fpath):
        for name in files:
            if(old_str.lower() in name.lower()):
                os.rename(os.path.join(path,name), os.path.join(path,
                                            name.lower().replace(old_str,new_str)))

I am replacing all occurences of old_str with any case by new_str.

Answered By: kiriloff
directoryName = "Photographs"
filePath = os.path.abspath(directoryName)
filePathWithSlash = filePath + "\"

for counter, filename in enumerate(os.listdir(directoryName)):

    filenameWithPath = os.path.join(filePathWithSlash, filename)

    os.rename(filenameWithPath, filenameWithPath.replace(filename,"DSC_" + 
          str(counter).zfill(4) + ".jpg" ))

# e.g. filename = "photo1.jpg", directory = "c:usersPhotographs"        
# The string.replace call swaps in the new filename into 
# the current filename within the filenameWitPath string. Which    
# is then used by os.rename to rename the file in place, using the  
# current (unmodified) filenameWithPath.

# os.listdir delivers the filename(s) from the directory
# however in attempting to "rename" the file using os 
# a specific location of the file to be renamed is required.

# this code is from Windows 
Answered By: frank__aguirre

as to me in my directory I have multiple subdir, each subdir has lots of images I want to change all the subdir images to 1.jpg ~ n.jpg

def batch_rename():
    base_dir = 'F:/ad_samples/test_samples/'
    sub_dir_list = glob.glob(base_dir + '*')
    # print sub_dir_list # like that ['F:/dir1', 'F:/dir2']
    for dir_item in sub_dir_list:
        files = glob.glob(dir_item + '/*.jpg')
        i = 0
        for f in files:
            os.rename(f, os.path.join(dir_item, str(i) + '.jpg'))
            i += 1

(mys own answer)https://stackoverflow.com/a/45734381/6329006

Answered By: Jayhello

I had a similar problem, but I wanted to append text to the beginning of the file name of all files in a directory and used a similar method. See example below:

folder = r"R:mystuffGIS_ProjectsWebsite2017PDF"

import os


for root, dirs, filenames in os.walk(folder):


for filename in filenames:  
    fullpath = os.path.join(root, filename)  
    filename_split = os.path.splitext(filename) # filename will be filename_split[0] and extension will be filename_split[1])
    print fullpath
    print filename_split[0]
    print filename_split[1]
    os.rename(os.path.join(root, filename), os.path.join(root, "NewText_2017_" + filename_split[0] + filename_split[1]))
Answered By: Amber Davis
#  another regex version
#  usage example:
#  replacing an underscore in the filename with today's date
#  rename_files('..\output', '(.*)(_)(.*.CSV)', 'g<1>_20180402_g<3>')
def rename_files(path, pattern, replacement):
    for filename in os.listdir(path):
        if re.search(pattern, filename):
            new_filename = re.sub(pattern, replacement, filename)
            new_fullname = os.path.join(path, new_filename)
            old_fullname = os.path.join(path, filename)
            os.rename(old_fullname, new_fullname)
            print('Renamed: ' + old_fullname + ' to ' + new_fullname
Answered By: Dan

Be in the directory where you need to perform the renaming.

import os
# get the file name list to nameList
nameList = os.listdir() 
#loop through the name and rename
for fileName in nameList:
    rename=fileName[15:28]
    os.rename(fileName,rename)
#example:
#input fileName bulk like :20180707131932_IMG_4304.JPG
#output renamed bulk like :IMG_4304.JPG
Answered By: Ajay Chandran

This code will work

The function exactly takes two arguments f_patth as your path to rename file and new_name as your new name to the file.

import glob2
import os


def rename(f_path, new_name):
    filelist = glob2.glob(f_path + "*.ma")
    count = 0
    for file in filelist:
        print("File Count : ", count)
        filename = os.path.split(file)
        print(filename)
        new_filename = f_path + new_name + str(count + 1) + ".ma"
        os.rename(f_path+filename[1], new_filename)
        print(new_filename)
        count = count + 1
Answered By: murthy annavajhula

If you would like to modify file names in an editor (such as vim), the click library comes with the command click.edit(), which can be used to receive user input from an editor. Here is an example of how it can be used to refactor files in a directory.

import click
from pathlib import Path

# current directory
direc_to_refactor = Path(".")

# list of old file paths
old_paths = list(direc_to_refactor.iterdir())

# list of old file names
old_names = [str(p.name) for p in old_paths]

# modify old file names in an editor,
# and store them in a list of new file names
new_names = click.edit("n".join(old_names)).split("n")

# refactor the old file names
for i in range(len(old_paths)):
    old_paths[i].replace(direc_to_refactor / new_names[i])

I wrote a command line application that uses the same technique, but that reduces the volatility of this script, and comes with more options, such as recursive refactoring. Here is the link to the github page. This is useful if you like command line applications, and are interested in making some quick edits to file names. (My application is similar to the “bulkrename” command found in ranger).

Answered By: Jim Shaddix

Building off of Cesar Canassa comment above.

import os
[os.rename(f, f.replace(f[f.find('___'):], '')) for f in os.listdir('.') if not f.startswith('.')]

This will find three underscores (_) and replace them and everything after them with nothing (”).

Answered By: cappleby