Training a Snake to Clean my Desktop
Milnor
Posted on May 17, 2023
The Task
The final project in the Coding Nomads Python 101 course is to write (1) a Python script that automatically cleans your Desktop by moving all screenshots to a new folder; and (2) writing a blog post about said script.
I began the project by looking at my actual Desktop and thinking about how to tailor the stated task to meet my actual needs. A minimally acceptable solution is to create a new folder and transfer all .png
images into it, but that would hardly make a dent in the 99 items contained in C:\Users\MyName\Desktop
. Therefore, my revised plan is to automatically move:
Setting the Path to my Desktop
If I were coding this tool at work, the path to the Desktop would likely be set via a command line argument. However, we haven't "officially" learned to parse command line arguments with sys.argv()
or argparse
yet. Another option would be to prompt for user input, but during a lab exercise, I had a bad experience where I meant to type C:\Users\MyName\Desktop\TestFolder
, but I missed the \
key and hit Enter
early, mistakenly running faulty work-in-progress code against my actual Desktop! (Fortunately, that script crashed after moving a single file to where I didn't want it). In the interest of safety, I will hardcode the path thus:
desktop = pathlib.Path(r"C:\Users\MyName\Desktop\TestFolder")
Only after I've tested the script against TestDir
will I shorten the path to run things against my Desktop for real.
Giving credit where credit is due, Stack Overflow straightened me out when my initial code was wrong. The Windows path separator \
easily collides with Unicode escape sequences, so I added r
to create a raw string, slightly easier than escaping each path separator.
Creating the New Directories
Since I want to create a series of new directories, not just one, I iterated through a list of names, joining them to the desktop
path.
for sub_dir in ["CODE", "NOTES", "PDFS", "PICS"]:
new_dir = desktop.joinpath(sub_dir)
new_dir.mkdir(exist_ok=True)
The exist_ok
argument should make testing less tedious, since the script won't error out if run in succession without deleting the new folders in between.
Identifying and Relocating Files
A hefty for loop did all the heavy lifting.
# Filter for screenshots only
for each in desktop.iterdir():
if not each.is_file():
# Skip directories
continue
extension = each.suffix.lower()
# Create a new path for each file
if extension in [".c", ".h", ".py"]:
# put it in CODE
new_path = desktop / "CODE" / each.name
elif extension in [".md", ".rtf", ".txt"]:
# put it in NOTES
new_path = desktop / "NOTES" / each.name
elif extension == ".pdf":
# put it in PDFS
new_path = desktop / "PDFS" / each.name
elif extension in [".bmp", ".gif", ".jpg", ".jpeg", ".svg", ".png"]:
# put it in PICS
new_path = desktop / "PICS" / each.name
else:
continue
First, I iterated through every file on the Desktop using iterdir()
. Second, to recognize file types in a case-insensitive fashion, I converted the suffix of each file to lowercase and tested whether it was found in a list of file extensions belonging to the same category. Third, I set a new_path
variable with the future location of the file. As a convenience, pathlib.Path
supports building paths using the /
operator; I find that more readable than the joinpath()
method when you have multiple pieces to string together.
files_moved = 0
....
# Move the screenshot there
print(f"[!] Moving {each} to {new_path}...")
each.rename(new_path)
files_moved += 1
Finally, each
file from the for loop was moved to new_path
using the rename()
method. For my own edification, I added a files_moved
variable to quantify the work completed by the automation script.
Running it...
When I changed the path from the test directory to my actual Desktop, the script proudly reported [+] Successfully moved 41 files!
. This was nice and all, but a quick visual inspection told me that the PDFs stayed put. Notice that unlike the other categories of files, there is only one valid file extension for a PDF. The initial version of my code had a silly logic bug that was syntactically valid: elif extension == [".pdf"]:
. After quickly fixing that and re-running the script, 16 additional files were relocated.
Now, with my Desktop in a semblance of order, I can tackle individual subdirectories at my leisure and delete any files that do not spark joy.
Complete Code Listing
# Write a script that moves all files with the .png extension
# from one folder to another
""" Clean up my Desktop Automagically """
import pathlib
# Find the path to my Desktop
desktop = pathlib.Path(r"C:\Users\MyName\Desktop")
# Create a new folder
for sub_dir in ["CODE", "NOTES", "PDFS", "PICS"]:
new_dir = desktop.joinpath(sub_dir)
new_dir.mkdir(exist_ok=True)
files_moved = 0
# Filter for screenshots only
for each in desktop.iterdir():
if not each.is_file():
# Skip directories
continue
extension = each.suffix.lower()
# Create a new path for each file
if extension in [".c", ".h", ".py"]:
# put it in CODE
new_path = desktop / "CODE" / each.name
elif extension in [".md", ".rtf", ".txt"]:
# put it in NOTES
new_path = desktop / "NOTES" / each.name
elif extension == ".pdf":
# put it in PDFS
new_path = desktop / "PDFS" / each.name
elif extension in [".bmp", ".gif", ".jpg", ".jpeg", ".svg", ".png"]:
# put it in PICS
new_path = desktop / "PICS" / each.name
else:
continue
# Move the screenshot there
print(f"[!] Moving {each} to {new_path}...")
each.rename(new_path)
files_moved += 1
if files_moved > 0:
print(f"[+] Successfully moved {files_moved} files!")
Posted on May 17, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.