Help with shell script on selected finder images

Hi guys! I'm an automation noob and dipping my toes into it, have already automated some part of my workflow with KM/Hazel, but I'm struggling to make such a macro in KM:
For example, I'm selecting 4 images in a folder, and I want to run an ImageMagick "montage" shell script on them (it combines 4 images in a grid). Here's where my macro is at at the moment:

KM Macro image

CleanShot 2024-05-23 at 22.18.00

The variables fill with the needed info, I guess the part that's failing is the Execute Shell Script. I tried adding ENV_PATH info to my KM variables, it didn't help. If I run the same commands through Terminal it works.

PLEASE HALP! :smile:

If I can provide any more info on this, let me know

Putting aside ENV_PATH variables for the moment, the first thing that jumps to the eye is that you haven't specified the full path, on your system, to the montage executable.

The incantation

which montage

at the Terminal.app prompt, will tell you what that full path is.

1 Like

Hello there!

The which command gave me a certain path I tried to add, but alas, both options do not work (still nothing happens when I run the macro):

2 options

#1
CleanShot 2024-05-23 at 23.19.16
#2
CleanShot 2024-05-23 at 23.20.48

You can't use KM variables directly in shell scripts.%Images% needs to be $KMVAR_Images. And of the two versions of the command with path you tried, neither one looks correct to me. I think it should just be this:

/opt/homebrew/bin/montage 1024x1024 "$KMVAR_Images" montage.jpg

The quotes are important, too. Also, earlier on, with the cd %FolderPath%, you need to do the same thing:

cd "$KMVAR_FolderPath"

For more on this, see the wiki on variables in shell scripts:

https://wiki.keyboardmaestro.com/action/Execute_a_Shell_Script

-rob.

2 Likes

In addition, neither of your invocations of montage look right.

Assuming that the path to it is indeed:

/opt/homebrew/bin/montage

you should simply follow that with the expected arguments.

(not sure why you are adding the name montage again after the full path to the executable ? Is that expected ?)

The following pattern seems more likely:

/opt/homebrew/bin montage 1024 etc
/opt/homebrew/bin/montage 1024 etc

/opt/homebrew/bin/montage montage 1024 etc
/opt/homebrew/bin/montage 1024 etc

1 Like

Thank you a ton for the tips!

It seems to be progressing, as KM asked for access for desktop folder (which is where my files are located now).

Still, though, nothing happens upon running the macro. Again, if I run the same macro with the text straight from "Images" variable, it works in Terminal.

Please post your actual macro, which you can do using the Share button. It will make us helping you much simpler.

-rob.

Combine Images.kmmacros (3.8 KB)

This is the macro I exported from KM, thank you.

Easier to do if you upload your actual macro, rather than an image: How to Post/Upload Your Macro to the Forum

Cross-posting...

Is it a shell script or an actual ImageMagick command? Your wording, plus the optionless 1024x1024 suggests a script, in which case you'll need the path to that rather than ImageMagick itself.

The path quoting for your images is going to be... interesting. You need to quote for spaces in the individual file paths but retain the spaces between the paths so they are treated as separate arguments. This could be a place where you need to escape the spaces instead of double-quoting.

1 Like

This is definitely part of the problem. The proper form of the command is:

/opt/homebrew/bin/magick montage file1.jpg file2.jpg fileN.jpg montage.jpg

With that out of the way, though ... something about magick or perhaps just its montage command has real trouble with paths. I have built a macro that works, but only for files without spaces in their names. Why? Because I cannot use any form of quoting to protect spaces, or the magick montage command fails.

Here's the working macro:

Download Macro(s): Combine Images_rg.kmmacros (6.8 KB)

Macro screenshot

Macro notes
  • Macros are always disabled when imported into the Keyboard Maestro Editor.
    • The user must ensure the macro is enabled.
    • The user must also ensure the macro's parent macro-group is enabled.
System information
  • macOS 14.5
  • Keyboard Maestro v11.0.3

I have spent way too much time playing with this :), and I'm going to have to give up: I cannot find a way to quote spaces in filenames that works. The version above is the only variant I managed to get working at all. Things I tried:

  • Filtering filenames with quote for shell script
  • Using a regex to replace any spaces in the name with backslash-spaces
  • Wrapping the filenames in single quotes
  • Wrapping the filenames in double quotes
  • Wrapping the $KMVAR_local_theCommandString reference in the montage command in quotes. Even if you do this with files without any spaces in their names, the command fails!
  • Setting a var in the shell to the file paths, then using the var in the command.

I have absolutely no idea how to quote filenames such that montage will find them and spaces will be protected. Here's a bit from the log for a failure when I filtered for shell safe:

2024-05-24 06:28:56 Execute a Shell Script failed with script error: montage: unable to open image 'IMG_3380\': No such file or directory @ error/blob.c/OpenBlob/3596.
montage: no decode delegate for this image format `' @ error/constitute.c/ReadImage/746.
montage: unable to open image 'new.jpeg': No such file or directory @ error/blob.c/OpenBlob/3596.

The first line reveals the issue: ...unable to open image 'IMG_3380\': ... it see the backslash as the end of the filename. When using double quotes and no shell script filter, it does this:

montage: unable to open image '"/path/to/puzzlepix/IMG_3373.jpeg"': No such file or directory @ error/blob.c/OpenBlob/3596.

Either I'm not understanding the proper way to quote this (completely possible), or magick is doing something on its own to try to parse the filenames, and that's causing the problem. Experts, see anything?

-rob.

1 Like

This is nuts, thank you for all the work you did. I'll take a closer look at all of that later today, but it seems as if I opened up a can of worms with imagemagick.

I wonder if there are other ways to make a grid collage of images apart from imagemagick (apple shortcuts combine images didn't work all that well for me).

There are plenty, but much will depend on the amount of control and customisation you want.

But we should be able to get ImageMagick to work -- it'll help if you can give an example of a working Terminal command and also check to see if the montage you care calling is actually a shell script (that might be adding a bunch of "default" options to your arguments, then passing the lot to magick montage proper).

If the worst comes to the worst you should be able to use KM as a graphical front end to your shell script, allowing you to select files in the Finder for your shell script to use.

Please see my macro above—it works, except I can't figure out how to quote the filenames successfully.

As a test, I did this, and it works for any file:

Download Macro(s): Combine Images_silly_rg.kmmacros (8.7 KB)

Macro screenshot

Macro notes
  • Macros are always disabled when imported into the Keyboard Maestro Editor.
    • The user must ensure the macro is enabled.
    • The user must also ensure the macro's parent macro-group is enabled.
System information
  • macOS 14.5
  • Keyboard Maestro v11.0.3

It's the same macro as above, except instead of trying to run a shell script, it just types the commands into Terminal, and it works perfectly. The string it typed—which is the same string I send in the shell script variant except that I added the double-quotes—is this:

/opt/homebrew/bin/magick montage "IMG_3382.jpeg" "IMG_3380 new.jpeg" "IMG_3379.jpeg" "IMG_3378.jpeg" montage.jpg

That works exactly as expected. But I just cannot figure out how to quote it properly in the shell script command. As you can see in my earlier post, I tried all sorts of variants. I'm open to suggestions as to what I missed.

-rob.

I'm still waiting on homebrew to update before I can install Image Magick, but in the meantime I ripped this pattern from the end of the Quoting Strings section of the Wiki page. This works with cat, so may with magick:

cat test.kmmacros (2.0 KB)

1 Like

Thank you so much for all the time you spent on this, appreciate it. I tried the last macro with typing in terminal, works like a charm so far. I'll try the other script you made later today as well.

this bit is too hard for me to wrap my head around for now with all the commands in the line:

A philosophy of *nix systems is to have utilities dedicated to doing one thing well and to chain those utilities into a more complicated workflow -- kind of like KM's actions combining in a macro.

You take the output from one utility and pass it as input to the next using the | ("pipe").

echo echoes the value of your KM variable, which is passed on to tr.

tr (with no options, as here) translates any characters of the incoming string that are in the first list to that in the second. Here we're swapping any \r and/or \n -- so that covers Mac, Unix, and Windows end-of-lines -- to the null character \0.

The resulting single-line string is passed to xargs, which splits the string on the null character and passes each chunk as an argument to cat.

cat concatenates the files passed into it and, because of the output redirection >, writes the result to the file "myOut.txt" on the user's Desktop.

So what we're doing is taking the KM variable

/path/to/file1.txt
/path/to/file2.txt
/path/to/file3.txt
...

...and making the command

cat /path/to/file1.txt /path/to/file2.txt /path/to/file3.txt > ~/Desktop/myOut.txt

Any *nix guru will doubtless pick holes in most of what I've said :wink: -- but hopefully it's a good enough explanation that you can see what's going on and how we can use similar patterns to push KM "lists" into Shell Script actions, to be used as arguments to utilities like cat. And, possibly, magick.

1 Like