I am new to python and coding, as a first project, I am looking to create a python script which will traverse a folder structure and look inside each sub-folder and rename the files within to match the name of the sub-folder.
Example folder structure:
root folder
├── first sub-folder (Batman)
│ ├── filename.extension (joker.pdf)
│ └── filename.differentExtension (bane.jpg)
│
└── second sub-folder
├── filename.extension
└── filename.differentExtension
So after the script has completed, the result would look like the below:
root folder
├── first sub-folder (Batman)
│ ├── filename.extension (Batman.pdf)
│ └── filename.differentExtension (Batman.jpg)
│
└── second sub-folder
├── filename.extension
└── filename.differentExtension
I am looking for recommendations into how to approach this, I was thinking of using os.path.splitext to seperate the filename from the file extension, but i'm unsure how to change the filename to the sub-folder value and then concatenate the filename and file extension back together.
I would use os.walk
, and ntpath
with a recursive function, to walk all directories and subdirectories...renaming as you go. The following code can absolutely be compressed...but I wanted to make it more explicit to help your understanding of what's happening.
import os
import ntpath
print(os.getcwd()) # Information for testing
rootDir = "/home/user/eclipse-workspace/test" # Will start here
# Create a recursive function.
# This function will call itself, to pass in new directories it finds
def walkit(rootDir):
# os.walk gives you the name of the directory it's in,
# all the subdirs (as a list),
# and all the filesnames (as a list)
for thisDir, thisDir_subDirs, thisDir_files in os.walk(rootDir):
print("---------------------------")
print("This Directory =", thisDir, "\nSubdirectories:", thisDir_subDirs, "\nFiles:", thisDir_files)
# Loop through and change the filenames first
for filename in thisDir_files:
# Get JUST the filename with extension
basename = ntpath.basename(filename)
# Split the filename into name + extension
name, ext = os.path.splitext(basename)
# Next split the last directory off the full directory path.
# Returns a tuple, so you have to take the second element "[1]"
newname = ntpath.split(thisDir)[1]
# Python join to create a new name + extension
newfilename = ''.join([newname, ext])
# Set the source by joining the current FULL directory path and the FULL old name
src = os.path.join(thisDir, filename)
# Set the destination by joining the current FULL path plus the FULL NEW name
dst = os.path.join(thisDir, newfilename)
try: # Use try except to catch problems
print("Renaming '{}' to '{}' ... ".format(src, dst), end = '')
os.rename(src, dst) # Rename the file
print("OK") # Worked
except Exception as e: # Failed
print("FAILED! (ERROR:{})".format(str(e)))
# Now cycle through the list of subdirectories and
# send each directory back into the walkit function.
# As each loop calls the function, it winds itself a new level deep
# Each time the function finishes, it "UNwinds" itself one level
for rootDir in thisDir_subDirs:
walkit(rootDir)
# Start the first iteratin by calling the function with the first directory to be parsed
walkit(rootDir)
OUTPUT:
/home/user/eclipse-workspace/
---------------------------
This Directory = /home/user/eclipse-workspace/test
Subdirectories: ['robin', 'batman']
Files: []
---------------------------
This Directory = /home/user/eclipse-workspace/test/robin
Subdirectories: []
Files: ['riddler.jpg', 'penguin.pdf']
ext= .jpg
newfilename = robin.jpg
Renaming '/home/user/eclipse-workspace/test/robin/riddler.jpg' to '/home/user/eclipse-workspace/test/robin/robin.jpg' ... OK
ext= .pdf
newfilename = robin.pdf
Renaming '/home/user/eclipse-workspace/test/robin/penguin.pdf' to '/home/user/eclipse-workspace/test/robin/robin.pdf' ... OK
---------------------------
This Directory = /home/user/eclipse-workspace/test/batman
Subdirectories: []
Files: ['joker.pdf', 'bane.jpg']
ext= .pdf
newfilename = batman.pdf
Renaming '/home/user/eclipse-workspace/test/batman/joker.pdf' to '/home/user/eclipse-workspace/test/batman/batman.pdf' ... OK
ext= .jpg
newfilename = batman.jpg
Renaming '/home/user/eclipse-workspace/test/batman/bane.jpg' to '/home/user/eclipse-workspace/test/batman/batman.jpg' ... OK