I've recently started programming and have been working through some problems such as the one below:
Write a program that finds all files with a given prefix, such as spam001.txt, spam002.txt, and so on, in a single folder and locates any gaps in the numbering (such as if there is a spam001.txt and spam003.txt but no spam002.txt). Have the program rename all the later files to close this gap.
I was able to solve with below, but I can't imagine this being the most elegant solution - just seems very convoluted and overcomplicated. I would like to build good habits and train myself to write more efficient code - any suggestions for how can this be optimized/shortened?
#! python3
# fillGap.py - finds all files with given prefix in folder
# and locates gaps in numbering and fills the gap
import os, re, shutil
# Arguments: folder, prefix
def fillGap(folder, prefix):
# Create regex with prefix + number + extension
prefixRegex = re.compile(r'(%s)((\d)+)(\.[a-zA-Z0-9]+)' % prefix)
# Make sure folder path is absolute
folder = os.path.abspath(folder)
# Create list with all files that match regex
fileList = []
for item in os.listdir(folder):
if os.path.isfile(os.path.join(folder, item)) and prefixRegex.search(item):
fileList.append(item)
# Look for the starting number by incrementing, starting from 0
Number = 0
Completed = False
while True:
for filename in fileList:
mo = prefixRegex.search(filename)
if Number == int(mo.group(2)):
length = len(str(mo.group(2)))
fileList.remove(filename)
Completed = True
break
Number += 1
if Completed == True:
break
# Increment from starting number, finding next largest file and renaming
nextNumber = Number
while True:
for filename in fileList:
mo = prefixRegex.search(filename)
if nextNumber == int(mo.group(2)):
# New number including prefixed zero's
subNumber = '0' * (length - len(str((Number)))) + str(Number)
# New filename with updated number
newFileName = prefixRegex.sub(r'%s%s\4' % (prefix, subNumber), filename)
shutil.move(os.path.join(folder, filename), os.path.join(folder, newFileName))
fileList.remove(filename)
Number += 1
if len(fileList) == 0:
break
nextNumber += 1