Batch Rename files with different Prefixes but same file type using python

Question:

I am trying to rename my files incrementally with a counter starting at 1, which process them in a way depending on their prefix and same file extension.
The directory has the following files examples:

BS - foo.fxp
BS - bar.fxp
BS - baz.fxp
...
PD - qux.fxp
PD - quux.fxp
PD - corge.fxp
...
LD - grault.fxp
LD - garply.fxp 
LD - waldo.fxp
...
PL - fred.fxp
PL - plugh.fxp
PL - xyzzy.fxp
... 
DS - thud.fxp
... 
... 
... 

I am trying to rename all batches with the same prefix with an incremental counter.
I had the idea first of storing all prefixes (with os.split into a list or a collection) then using this list to scroll through the files in the directory.
I can’t figure out how to reset the counter when the prefix changes.
A resulting example would be:

BS - 1.fxp
BS - 2.fxp
BS - 3.fxp
...
PD - 1.fxp
PD - 2.fxp
PD - 3.fxp
PD - 4.fxp
...
... 

Here’s the original code but incrementing through all files and not per batch of prefix.

import os, glob
path ='foo/bar/fox' 

def prefix(f):
    if f.endswith('.fxp'): 
        return(f.split(' -')[0])

os.chdir(path)
count = 0 
for f in sorted(os.listdir(path), key = prefix):
    if prefix(f) == f.split(' -')[0]:
        count =+ 1
        new_name = prefix(f) + '_' + str(count)+ '.fxp'
        os.rename(f, new_name)

Any help is appreciated.

Asked By: Gnai

||

Answers:

I wrote this code for the same purpose back but you can modify it and re-use…

import os
# Function to rename multiple files
def main():
   i = 0
   path="path to files"
   for filename in os.listdir(path):
      t = os.path.splitext(os.path.basename(f)) 
      my_dest = t[0] + str(i) + t[0]
      my_source =path + filename
      my_dest =path + my_dest
      # rename() function will
      # rename all the files
      os.rename(my_source, my_dest)
      i += 1
# Driver Code
if __name__ == '__main__':
   # Calling main() function
   main()

Answered By: Masoomjethwa

For those who stumble upon this, I solved this in two steps:
Firstly, adding all file paths into a dict where the keys are equal to the prefixes in question in this case (BS, LD, PD, PL, DS…) and the values of those keys are equal to a list of strings with file paths with respect to each prefix with the following code block:

path ='foo/bar/fox' #directory path 
patches_dict = {}
os.chdir(path)

for root, dirs, files in os.walk(path):
    for file in files:
        if file.endswith('.fxp'):
            prefix, _ = file.split(' -')
            filepath = root + file
            prefix_dict[patch_type] = [filepath] if prefix not in prefix_dict else prefix_dict[prefix] + [filepath] 
            #method append value to list of specified key and if key doesn't exist it will create an empty list and add the value in question to that list

Second step would be to iterate through those values and in each key and enumerate the length of the list to be added to the name of the file path while keeping the prefix, see below:

for keys, values in prefix_dict.items(): #iterating through keys&values in dict
    for i, v in enumerate(values,1): #enumerate will start with 1 instead of 0
        old_path = v
        new_path = os.path.join( os.path.dirname(v) + '/' + keys +str(i) + '.fxp')
        os.rename(v, new_path)

Thank you SO community 🙂 !

Answered By: Gnai
Categories: questions Tags: , , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.