Folder sync with Shortcuts on Mac OS

Photo by Romain Virtuel on Unsplash

Did you know there is no way to recursively copy a folder skipping over all the existing items using Finder on a Mac? Recursive copy means copy all the files in the folder, and do the same for each subfolder and so on until the whole folder structure is parsed. If you copy a folder with subfolders from Finder, the operation will be blind: it will take all subfolders, see if they exist at the destination, if they do, you will be asked what you want to do: skip or overwrite. There is no “copy newer files only” option.

But this is not really a Mac issue. No graphical file manager to date on any operating system is able to handle folder synchronization correctly. They all implement a form of shallow copy: get all files and folders, if they exist already you can either skip or overwrite. No file manager would get into each folder recursively and check for file existence at the destination and skip the existing files.

Of course, the terminal in all operating systems allows us to do this easily. In Linux and Mac we have the rsync tool which does exactly this: takes one folder and copies it to a destination folder, while checking to see what files are already there. And yes, rsync can fully synchronize two folders this way, deleting extra files at the destination if they are not in the source folder too. Windows has xcopy, robocopy and many others, not to mention native PowerShell scripting.

But we don’t want to open the terminal each time we need to recursively copy a folder. And this is where most operating systems fail to provide. Let’s learn about Mac OS Shortcuts!

Photo by Toa Heftiba on Unsplash

The Shortcuts app is kind of new in the Mac OS suite of useful tools, but there were ways to automate tasks before it. You have AppleScript and the Mac OS Automator app, both of which can execute tasks on demand. But Shortcuts is different by allowing users to automate tasks using a nice graphical builder and also assigning tasks to application’s Quick Actions menu automatically, as we will see in a moment.

First, if we start the Shortcuts app we can browse a gallery of shortcuts, designed to give us a sense of what it can do: “Turn text into audio”, “How many days until”, “Upload last photo” and so on:

Initial screen of the Mac OS Shortcuts application

A shortcut is basically a set of actions performed on given inputs. The input can be a photo, a Finder selection or any object provided by a Mac OS app. In our case since we are dealing with folders, the shortcut input will be two folders: the source and the destination.

Photo by Scott Blake on Unsplash

We create a new shortcut by clicking on the New Shortcut button having a plus icon in the All Shortcuts tab. This will present the shortcut builder screen:

The shortcut builder screen

We give it a name by editing the “Shortcut Name” text in the toolbar. Let’s call it “Recursive copy” or “Test” if you are just playing. Next we set the shortcut to be a Finder quick action by clicking on the “Shortcut Details” button having an “i” icon in the right sidebar, right at the top. We check “Use as Quick Action” and “Finder” in the sidebar:

Configuring the shortcut input

This will add an input panel to the shortcut, configured by default to work with anything right clicked in Finder. We want to narrow this down to folders, so we click on the blue “Any” button and deselect everything except “Folders”:

Configuring the shortcut input

The input allows us to react in case there is nothing selected, for example if we run the shortcut by pressing the “Play” button in the shortcut builder toolbar. If we do this instead of right clicking on a folder in Finder, there is no input available. So let’s click on the blue “Continue” button and select “Ask For” and choose “Files”:

Ask for files in case there is no proper input

We have the source folder, now we need the destination folder. Let’s click on the “Action Library” button at the top of the right sidebar to list all the actions we can use, and search for “Select file”. Drag it to the workflow:

We don’t need files, we need a folder, so we click on “Files” and choose “Folders”:

Configuring the destination folder input

Note that the “Select Folders” action allows us to have multiple folders selected by clicking on the top right “Show More” button. In this case the destination is a single folder so we leave it unchecked.

Photo by Lucas Vasques on Unsplash

We have two folders selected but we need their paths to use them as a source and destination of our synchronization. So let’s search for the “Get Details of Files” action in the right sidebar and add it for both inputs by dragging it twice in the workflow:

Getting the required information from the selection

We configure both to get the name by clicking on “Detail” and selecting “File Path”:

Getting the file paths for both inputs
Photo by Crissy Jarvis on Unsplash

We have the paths, now we need them in an array of strings so we can pass them to our synchronization script. Let’s search for “variable” in the Action Library and again, add it twice to our workflow, one for each input:

Adding our inputs to a single variable

Now our inputs are consolidated in a single variable. Since the variable contains two string values, it takes the form of a string array. Basically it looks something like this: [“path1”, “path2”]. Note the “Variable Name” button in the “Add to Variable” action. We can set a name for our variable by clicking it:

Setting the variable name

We can see the content of the variable by adding a “Show Result” action at the end of the flow, and configuring it to display our variable:

Displaying the array of string paths
Photo by Jakob Owens on Unsplash

We have our inputs: the source folder path and the destination folder path, all we need to do is create a script to recursively copy everything from the source to the destination. To do that, we add a “Run Shell Script” action to the workflow:

Adding a Run Shell Script action to the workflow

The input should be configured to be the “Parameters” variable, but we need to switch “Pass Input” to be “as arguments”. This will make our string array usable by the shell script. Next we write our shell command. We will use rsync, without altering the destination. So the command is a simple:

rsync -r source destination

The -r parameter means rsync will run recursively across the entire folder structure. And to use our shell parameters we will replace source and destination with $1 and $2, meaning the first value of our “Parameters” array and the second:

The final script for the Recursive copy shortcut

Note we are grabbing the content of the first folder, not the folder as is because that will copy the parent folder too in the destination. To avoid that, we use $1/* which means get all files and folders from the source path, not the source path itself.

We are done. While we were busy writing the shortcut, Finder already updated itself to show it in the Quick Actions context menu. If it’s not there we can right click on a folder in Finder, click on Quick Actions and click Customize:

Checking Recursive copy in Finder’s Quick Actions customization screen

Next time we right click on a folder in Finder, we will see our shortcut:

The Recursive copy quick action

If we click on it, the shortcut will ask us to pick a folder as the destination, and after that it will run the synchronization script.

I hope this article will be useful to you. There are many things you can do with shortcuts and this is just a small showcase which I use a lot. Of course we can add a certain output to the shortcut to indicate when everything is done but maybe in a future article. For now, thanks for reading and see you next time!



Still planning that trip to the Moon.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store