BYU Student Author: @klayton
Reviewers: @Parker_Sherwood @Mike_Paulsin, @Jonathan_Weston
Estimated Time to Solve: 20 Minutes
We provide the solution to this challenge using:
Need a program? Click here.
Overview
You are a new employee at a local accounting firm, and in your entry level position you are often tasked with the more menial tasks. One of these tasks is moving all the invoices you send to clients from the “Invoices to Send” folder into their specific client folders. Manually moving all these files can be very time consuming, and you want to impress your new boss by finding a way to perform this task quickly and accurately.
The following packages might help in this challenge, glob, shutil, and re (regex), but feel free to use any you like!
Instructions
Create a function in python that has the following specifications:
- Name your function “move_files”
- It must take input for the beginning and destination folders’ filepaths.
- The script should check to make sure the string for the filepath ends with “\” and either add the “\” if it isn’t there or prompt the user to try again and add the slash themselves.
- Use glob to put all the files into a list.
- The file names should stay the same in the transfer.
- The attached zip folder contains the invoices as well as the client folders. The invoice files should be moved into the folder “invoices” in their respective client folder.
Data Files
Suggestions and Hints
- In python “\” is a special character that changes the meaning of the following character, so when checking for that character at the end of a string use “\” instead of “\”. The latter will ignore the end quotation mark and cause errors.
- Use “Print()” often to check what is happening in your code.
- The glob module in Python is used to retrieve file paths that match a specified pattern, allowing users to easily search for files and directories with specific names or extensions.
- The shutil module in Python provides a higher-level interface for file operations, including copying, moving, renaming, and deleting files and directories, making it easier for users to manage file operations on their system.
Solution
import glob
import shutil
import re
def move_files(src_folder, dest_folder):
# Ensure the filepaths end with a backslash
if not src_folder.endswith("\\"):
src_folder += "\\"
if not dest_folder.endswith("\\"):
dest_folder += "\\"
# Use glob to put all the files into a list
file_list = glob.glob(src_folder + "*.*")
# Iterate through the files and move them to the respective client folders
for file in file_list:
# Extract the client name from the file name using regex
client_name = re.search(r'client\d+', file).group()
# Define the destination path for the invoice
dest_path = dest_folder + client_name + "\\invoices\\"
# Move the file to the destination path
shutil.move(file, dest_path)
print("Files moved successfully.")
# Example usage
src_folder = "path\\to\\InvoicesToSend"
dest_folder = "path\\to\\ClientFolders"
move_files(src_folder, dest_folder)
1 Like
This was a great challenge! I ended up using an input statement get the file path for the folder to get past most of the double backslash issues.
Here’s my solution:
from glob import glob
import shutil
import os
#Create a directory for the Challenge PDF Mover folder and a directory for wherever your python notebook operates.
#Include an os.makedirs statement in case you create filepaths that do not exist.
folder_directory = input('Please enter the file path for the Challenge PDF Merger Folder.')
if folder_directory[-2] != '\\':
folder_directory = folder_directory + '\\'
directory = os.getcwd()+'\\'
os.makedirs(os.path.dirname(directory), exist_ok=True)
#Create a list of the invoices within the Challenge folder
invoices = glob(folder_directory+'*.pdf')
#Loop through each client folder and create a directory
for invoice in invoices:
invoice = invoice.split('\\')[-1]
client = invoice.split('#')[0]
client_invoice_directory = folder_directory+'\\Client Folders\\'+client+'\\Invoices\\'
#Move the file from the challenge folder into the client's folder.
shutil.move(folder_directory+invoice,client_invoice_directory+invoice)
1 Like
import os
import shutil
import glob
def move_files(src_folder, dst_folder):
# folders must end with \
# prompt user to ender correct syntax
if not src_folder.endswith('\\'):
print(f"The source folder path '{src_folder}' is missing a trailing backslash. Please add it and try again.")
return
if not dst_folder.endswith('\\'):
print(f"The destination folder path '{dst_folder}' is missing a trailing backslash. Please add it and try again.")
return
# Get a list of all files in first folder
lFile = glob.glob(os.path.join(src_folder, '*'))
# Move each file to the invoices subfolder of its client folder in dst_folder
for oFile in lFile:
#get client name
client_name = os.path.splitext(os.path.basename(oFile))[0]
# make new folder for destination
client_folder = os.path.join(dst_folder, client_name)
invoices_folder = os.path.join(client_folder, 'invoices')
# Create the client and invoices folders if they don't exist
os.makedirs(invoices_folder, exist_ok=True)
# Move invoices folder
shutil.move(oFile, invoices_folder)
#print concatenated statement
print(f"Moved file '{oFile}' to '{invoices_folder}'")
1 Like
Great challenge! It was my first time using glob. I really like how easy it is to find all the pdfs in the file. My solution was similar to Jonathan’s and Hunters.
I see how this could be really beneficial in the workplace to help automate mundane tasks. Looking forward to using this in the future, hopefully I have an opportunity to use this during my internship.
1 Like
Interesting challenge highlight a very practical use of the Glob module!
I ended up using Regex grouping with re.findall() which was a fun challenge. I also used os.path.exists to make sure the starting and ending filepaths were valid directories before entering the function.
# Import relevant files
from glob import glob
import os
import re
import shutil
def move_files(start_path, dest_path):
# Get all files in a list
files = glob(start_path + '*.pdf')
for file in files:
# parse out client name using Regex grouping
client_name = re.findall(r'.*(\d{6})#\d+[a-zA-Z]?.pdf', file)
# Move into relevant folder
shutil.move(file, dest_path+client_name[0]+'\\Invoices\\')
print('Files have been moved!')
while True:
start_path = input('Please enter source folder: ')
dest_path = input('Please enter destination folder: ')
if start_path[-1] != '\\':
start_path = start_path + '\\'
if dest_path[-1] != '\\':
dest_path = dest_path + '\\'
if os.path.exists(start_path) == True and os.path.exists(dest_path) == True:
# exists loop only when filepaths are valid
break
else:
print('Filepath is invalid. Please try again.\n')
move_files(start_path, dest_path)
1 Like