Here is the workaround that I used to circumvent this issue. I was trying to run a simple shell script, but the same workaround would apply to a Python script. To summarize, the steps involved are:
- Create an automator application called e.g. run-script.app that has a single bash script which runs whatever file is passed to it
- Either give the full automator application Full Disk Access via Security & Privacy or run it once manually and click Allow when macOS prompts for permissions
- Call the automator application with whatever script you want to run
More details:
- Whatever script you're wanting to run, make sure it's executable (using
chmod +x
) and that you have the right #!
line at the top of the script (e.g. #!/bin/bash
). In this example, I'll use a script at ~/scripts/organize-screenshots.sh
that moves screenshots from my desktop to my Google Drive directory:
#!/bin/bash
user_dir="/Users/soxley"
find "$user_dir"/Desktop -name 'Screen Shot *.png' -exec mv {} "$user_dir"/Google\ Drive/pictures/screenshots/ \;
- Next, create an Automator application:
- Open Automator
- Click New Document
- Select Application
- Click Choose
- Select Utilities > Run Shell Script
- Select Pass Input: as arguments
- Enter
/bin/bash -c "$1"
as the body of the script (see screenshot below)
- Click File > Save and save the application wherever you'd like (
run-script.app
in this example)
- Next, run the application that was just created manually to make sure it has the permissions it needs (you could also grant Full Disk Access to the new application in Security & Privacy):
- Open Terminal.app
- Execute the command
open -a run-script.app organize-screenshots.sh
- Click Allow when macOS asks if the application can access your Desktop
- Now you're ready to configure your script in launchd. Update your .plist with the following
ProgramArguments
:
<key>ProgramArguments</key>
<array>
<string>open</string>
<string>-a</string>
<string>/Users/soxley/scripts/run-script.app</string>
<string>/Users/soxley/scripts/organize-screenshots.sh</string>
</array>
Now you should be able to run whatever script you want using this application as a wrapper.
