Shortcuts shell script & regex tips for working with file automation

Been experimenting with moving some of my Hazel automations over to Shortcuts. Thought I would share some of the less-obvious solutions I discovered resolving errors.

Pass A File From Folder Actions To Shortcuts

I set up some Shortcuts with the intent of them being triggered by Folder Actions on macOS. You need to make a special Workflow to run a Shortcut via Folder Actions, but I was having trouble getting the file itself to be passed into Shortcuts from the Folder Actions Workflow.

This shell script in the Automator workflow that worked for me to pass the file into the desired Shortcut:

shortcuts run "your Shortcut here" -i "$1"

You also need to have the “Pass input” menu set to “as arguments”.

The -i "$1" was the part I added to the base code. Once that was added, it treated the file as you’d expect when just running a Shortcut on a file in the Finder. Without it, the workflow was only passing the file path as text to Shortcuts, and prevented me from working with the contents of the file.

I deduced this from this Apple documentation.

Perhaps there is a way to use that file path to work with the actual file, but I was unable to figure it out.

“OR” Logic Using Regex, and Non-Matching Groups

The other thing I was dealing with was creating a regex that would analyze the text of a CSV of PDF file, in order to extract a date-month string to be used to rename the files.

Getting the text was the easy part. There were two other issues I needed to fix.

  1. How do I match multiple possible document naming scenarios (“OR” logic) without a convoluted Shortcut logic tree, and without the resulting group being indexed as a matching group?

The regex to do non-indexed “OR” matches looks like this:


The pipe is the OR symbol. The parentheses are the group. The opening question mark and colon is what tells the regex to ignore it as an indexed group. It will be used only for matching purposes. I was running into issues by not grouping these OR items.

In my specific instance, I was trying to match different variations for filenames of CSV files I download on a regular basis.

Limit Regex Matches to First Match Instance

  1. How do I stop regex from finding group matches in the entire document? Being a transactions CSV, there can be hundreds of matches for the date pattern I was trying to match, and extract for file renaming.

Turns out it is relatively simple to have the regex stop after it finds the first match:


Just prepend the matched groups by the ? string. The regex will stop matching after it finds the first matching string.

Here is an example of how I did this for a string to capture the typical 4-digit year and 2-digit month (2024-01):


Match Any Character, Including Line-Breaks

A third regex snippet also helped me get past the inability to have the regex match ‘any character’ (a period) and include line breaks, because it turns out the period is actually ‘any character except line breaks’.

Here is the regex:


Again, it makes this a non-capturing group, uses the OR logic, and just says “match any character (.) or any line break (\n)”.

These few regex snippets really opened up Shortcuts for me to be able to do a lot of the things I was using Hazel to do. I thought they might be helpful i a lot of contexts beyond my specific needs, and because none of this was very obvious when I headed down this rabbit hole initially.

I am using my iPad Pro more and more as a main device, and not having my file sorting automations on iOS was becoming less and less tolerable. And maintaining just one set of automations is much better than trying to keep different sets up to date for macOS and iOS. And in completely different apps as well.

A couple of alternatives to the last one:

  1. (?s). = “s” is a flag that makes the period to also match line breaks
  2. \X = Unicode version of “match anything”

Also, sometimes line breaks are \r\n instead of just \n. So if there’s any chance of that, \r?\n can be used to cover both cases.

1 Like

Good to know, that’s even better. Thanks!