Receiving multiple files, not just one, in a Shortcut on macOS 12 Monterey

Solution 1:

To avoid processing a list of file paths in your shell script just loop over the input with Repeat with Each and pass each file path as the script argument with a Shortcuts variable. Quote it to keep spaces and other special characters present in the path. A screenshot of Shortcuts looping over multiple files

Solution 2:

Ran into the same issue while trying to port some Automator scripts to Shortcuts. So frustrating. I really hope there's a better approach than the workaround I came up with.

Here's what ended up working for me:

1. Start with the "Combine Text" action

2. Right click on "Text List," hover over "Select Variable" and choose "Shortcut Input"

3. Left click on "Shortcut Input" and select "File Path". Make sure "With New Lines" is selected

This will combine the input file paths with newlines.

4. Convert the newline-separated filename input into an array and iterate over it.

I tried a few other ways of combining / replacing the file paths prior to the shell script (e.g. sending them in as quoted strings separated by a space -- "file 1" "file 2") to see if I could make "$@" work as it normally does, but I gave up after a while. No matter what I did "$1" looked just like "$@". So I ended up with something custom.


Shell script

Here's the shell script for easy copy/paste (should work on bash and zsh by just modifying the index of FILES in the dirname command for bash as noted in the comments):

# Expects a file path or newline-separated list of file paths

# Change Internal Field Separator (IFS) to newline,
# convert the input file paths(s) into an array (uses IFS),
# then revert IFS
OLDIFS="$IFS"
IFS=$'\n'
FILES=($(echo $@))
IFS="$OLDIFS"

# If needed, e.g. to created a new sub-directory for output, 
# cd to the files' directory using the first item in the array
# (change index to 0 if bash -- zsh arrays start at 1)
cd "$(dirname "${FILES[1]}")"
# mkdir -p ./output # Example: create a directory for output

# Iterate over the files in the array
for FILE in "${FILES[@]}"; do
  # Do stuff with $FILE here
done

All together

Make sure in the Shell Script to choose "Input: Combined Text" and "Pass Input: as arguments"