Overview

Workflow tip on automating folder creation in the Mac Finder. We will be using the simplicity of the Python programming language to build a tiny program that will take care of generating a complete folder hierarchy for our projects, based on a predefined template.

Throughout, we will also cover some basics of Python programming and point to resources that can help you learn more about it.

Here is the final script we will be writing - for quick reference. If you already know what you are doing, just paste it into a new text file and save it with a .py extension. You can then duplicate the createFolder line while swapping the My New folder names with your own folder names to create your own folder hierarchy template. Then, look at the Running Our Program section for how to run the script, or follow the step by step guide below to understand what's going on.

import os

def createFolder(folder):
    try:
        if not os.path.exists(folder):
            os.makedirs(folder)
    except OSError:
        print('Error creating folder: ' +  folder)
        
createFolder('My New Folder')
createFolder('My New Folder/My New Subfolder')

Note: You can find this example and additional ready to use project templates on our github page.


Getting Started

If you are not familiar with Python follow these steps first to check if its installed on your system:

  1. Open the Terminal App (from the Applications folder or search for it in Spotlight)
  2. Type python3 --version or python3 -V. Then press enter on your keyboard to get the version of python installed on your Mac.
  3. If you get a message saying command not found, try the same command without the 3 to check if an older version of python is installed. If you get a similar message, download the latest Python here: https://www.python.org/downloads

Note: MacOS from 10.2 (Jaguar) to 10.15 (Catalina) includes a system version of Python 2. MacOS after 10.15 (Catalina) will not include a default system Python. More info here: https://wiki.python.org/moin/BeginnersGuide/Download

If a version number appeared, you have Python installed.

Note: At the time of writing there are two Python versions available: Python 2 and Python 3. Python 3 is recommended but not essential for our program to work.

Here is a digestible description of what Python is, what it does, and where it's used: https://www.pythonforbeginners.com/learn-python/what-is-python/

Code Editor

Next, you need a code editor. If you don't have one already there are plenty of options that you can find online. But for the time being let's use the default one that comes with the Python installation: IDLE.

To open IDLE, launch the Terminal app. Then type idle and hit enter on your keyboard.

The IDLE editor should launch.

Select the open window. Now go to File -> New File. Or press Ctrl + N for a new file. This new window is where we will write our program.

Note: You can quit IDLE like any other Mac app.


Writing the Program

The goal of our program is to create a hierarchy of folders in the Finder based on a template we provide.

OS Module

To allow Python to interact with the Finder, that is part of the Mac OS, we need to import the os (operating system) module first.

We can import the module by writing:

import os

Next, we are going to create a new function. A function is simply a task that can be called anytime once its declared and it will run any commands we specified within it. We will use it to perform the task of creating a new folder with a specified name. We will then be able to call it to create however many folders we choose to specify.

Writing Our Main Function

To declare a function in Python we can write:

def createFolder(folder):
	# More code here...

Notice a few things:

  1. def is the term used to define a function.
  2. createFolder is the name of our function (you can name it whatever you want as long as you don't use any reserved words or characters, or whitespaces). To play it safe just use lower or UPPERCASE characters, and _ underscores or - dashes.
  3. The parenthesis are used to pass in arguments, defined when calling the function (will make sense later on).
  4. The colon : signifies the start of the function's content.
  5. The content can then be written on a new line but needs to have a tabbed space before it, to define it as such.
  6. In our example the # defines a comment in Python. You can add this symbol before any line of code to have it ignored by the interpreter - it won't execute.

Handling Errors

Moving on, let's add a snippet of code for error handling. This is a best practice and is important for helping us find out if something is wrong with our program. It looks like this:

try:
	code1
except:
	# error encountered
	code2

It tells the interpreter to try running code1. If an error is encountered, run code2 instead.

We can add this content in our function like this:

def createFolder(folder):
	try:
		# do something
	except OSError:
		# do something else

Notice how the OSError has been added just after except. This is known as an exception and it's used when you want to check for a specific kind of error. OSError handles file errors, such as if a file fails to be read or written to. Since we are working with files we can use this exception.

Note: For a list of Python exceptions see https://docs.python.org/3.8/library/exceptions.html

Create a folder

In our try block let's write our command to create a folder in Finder, and in our except block let's output a message to notify us if there is an error, and what folder caused it.

The print command outputs a readable message as specified in the parenthesis. The + symbol is used to concatenate our error message and the current folder name.

def createFolder(folder):
	try:
		os.makedirs(folder)
	except OSError:
		print('Error creating folder: ' +  folder)

The command for creating a folder in Finder is makedirs (make directories), and we are passing the name of the folder that needs to be created in the parenthesis - this will become clear in the next subsection...

Since the command belongs to the os module we specify it by calling the module first, followed by a period and the command. The period suggests that the command belongs to that module: module.command() -> os.makedirs().

Calling Our Function

We are now ready to call the function so it can run the commands we specified.

Below the function and without tabbed spaces, we can write:

def createFolder(folder):
	try:
		os.makedirs(folder)
	except OSError:
		print ('Error creating folder: ' +  folder)

createFolder('My New Folder')

This will call the function we declared earlier and we finally see what the folder argument in the parenthesis stands for. In essence, when calling a function we can pass parameters to it (known as arguments). Those can then be used within that function.

Note: We can name the argument whatever we want, again with the limitation of avoiding reserved characters or words, or whitespaces. Essentially the argument name can only be used within that function. If used outside, an error would be thrown.

In the example we are calling the function and passing the name of the folder (in the parenthesis) with it. Notice the single quotes around 'My New Folder'. Those are necessary and state that the sequence of characters or words specified are to be interpreted as a String. You can use single or double quotes but it's a good idea to stick to one or the other. More about Strings here: https://www.programiz.com/python-programming/string.

Once the folder is created, we can create a subfolder by specifying the parent folder name first, followed by a forward slash and the subfolder name:

createFolder('My New Folder')
createFolder('My New Folder/My New Subfolder')

Note: We do not need to specify the full folder path since those are relative to the working directory from which we launched the program (see the Running Our Program section below).

Error: Folder Already Created

If we were to run this program it should hopefully not throw any errors. But if we were to run it again, it would definitely throw an error, since it would try to create a folder that already exists - it will halt the program and prevent overwriting.

But we want the program to continue creating folders aside from the ones that already exist.

To do this we can use an if statement to perform a check. An if statement allows us to run a command based on whether the statement, once checked, results as True or False. In our case we will check if the folder already exists. If it does not, the program will proceed with the creation of the new folder. If it does, we will skip folder creation for that folder.

Ordinarily we could write something like this:

if os.path.exists(folder):
	# True: folder exists
else:
	# False: folder does not exist so create it

But we want to simplify our code! We can therefore invert the statement so it evaluates True if the folder does not exist, and we can omit the else altogether. To invert the statement we can use the not operator.

And we end up with:

if not os.path.exists(folder):
	# True: folder does not exist

Save

Let's save the file by going to File -> Save. Or pressing Ctrl + S on your keyboard (not Cmd + S). Name it myProjectTemplate or whatever you prefer. Choose a directory or just save it to the Desktop.

That's it we can now attempt to run the program and see what happens...


Running Our Program

Create a new folder in Finder (e.g. on your Desktop) and call it New Project or whatever you want.

Open a new Terminal window.

Type cd to change directory, then tap on the spacebar. Now drag and drop the folder you previously created to the Terminal window. You should have something like this:

cd /Users/your_username/Desktop/New\ Project

Press enter on your keyboard - you now changed the working directory to the New Project folder.

Now type python if you have Python 2 installed or python3 if you have Python 3 installed. Hit spacebar once, then drag and drop your python script myProjectTemplate.py to the Terminal window.

# python 2
python /Users/your_username/Desktop/myProjectTemplate.py

# python 3
python3 /Users/your_username/Desktop/myProjectTemplate.py

Hit enter.

If you navigate to the New Project folder in Finder, you should see the new created folders.


Additional Resources

Gfxhacks Gists on Github:

gfxhacks’s gists
GitHub Gist: star and fork gfxhacks’s gists by creating an account on GitHub.

Download Python:

Download Python
The official home of the Python Programming Language

Hitchhiker's Guide to Python:

The Hitchhiker’s Guide to Python! — The Hitchhiker’s Guide to Python
An opinionated guide to the Python programming language and a best practice handbook to the installation, configuration, and usage of Python on a daily basis.

If you are new to Python, check out this introduction:

Python Introduction, What is Python, What can you do with Python | jobtensor

Code from your browser:

The collaborative browser based IDE
Repl.it is a simple yet powerful online IDE, Editor, Compiler, Interpreter, and REPL. Code, compile, run, and host in 50+ programming languages: Clojure, Haskell, Kotlin (beta), QBasic, Forth, LOLCODE, BrainF, Emoticon, Bloop, Unlambda, JavaScript, CoffeeScript, Scheme, APL, Lua, Python 2.7, Ruby, R…

Another useful Finder automation tip:

GFXHacks - Automate File Renaming in Finder (OSX)
Renaming files can be an incredibly tedious task, especially when faced with hundreds of items. This can prevent us from being organized, often impacting our time and resources elsewhere in our workflows. Automation is key to ensure we keep files organized without wasting time doing it.