Variable in Shell Script for Printing

I'm new to Keyboard Maestro, I'm been used to windows and AutoHotKeys.
I know I'm probally missing something stupid but can someone help me. It's a simple shell script that uses the printer I want with all the settings I want but I can't get the file variable to work in the script.

Only thing I can get to work is the script will print the file path plain text but doesn't print the file if I run the script in terminal with file path it works fine so I know it has to be something I'm doing wrong with passing the file path using the variable.

Screenshot 2024-03-28 at 5.46.04 PM

You don't include the file name in the command line that prints. For example (simplified):

lp "$KMVAR_localFile"

I'd recommend using a local variable for this because you don't need to save the file name between invocations.

For more on printing from the command line, see Command-Line Printing and Options.

That didn't work the code I'm using in Hazel is
lp -d XeroxC8145 -o ColorModel=RGB -o Duplex=DuplexTumble -o InputSlot=tray-4 -n 2 "$1"

It works and at the end of the code "$1" is where I was trying to replace with the KMVAR Variable but it doesn't work

Take a look at the logs (easily accessed from the Help menu in the Keyboard Maestro editor itself) to see if your command line is throwing any errors.

Thank you for trying to help like I said I'm new to this system didn't know about the help log there isn't any good tutorials I have found on YouTube to learn this system.

Error log is showing

2024-03-28 20:21:29 Action 13599616 failed: Execute a Shell Script failed with script error: lp: Error - unable to access “” - No such file or directory
2024-03-28 20:21:29 Execute a Shell Script failed with script error: lp: Error - unable to access “” - No such file or directory. Macro “Printer” cancelled (while executing Execute Shell Script).

Weird thing is I can get it to work in the terminal and I can get it to work using Hazel but can't get it to work with Keyboard Maestro

Okay so I'm at home now so having to use a different printer than what I use at work and its now passing the file path but still giving a error

2024-03-28 20:29:28 Execute macro “Printer” from trigger Anything is added to folder “~/Desktop/For Printing” (ignoring partial files)
2024-03-28 20:29:28 Action 13599616 failed: Execute a Shell Script failed with script error: lp: Error - unable to access “/Users/nathanclark/Downloads/1569154-2.pdf” - No such file or directory
2024-03-28 20:29:28 Execute a Shell Script failed with script error: lp: Error - unable to access “/Users/nathanclark/Downloads/1569154-2.pdf” - No such file or directory. Macro “Printer” cancelled (while executing Execute Shell Script).

One debugging approach you might try is to use the Display Text action to show you the command line you're constructing and compare that to the two that work.

I can't imagine that Keyboard Maestro doesn't have permission to access folders on your Desktop but you might want to ensure it has Files and Folders access in System Settings > Privacy & Security (or some such, depending on your version of macOS).

Okay I finally have it working

Probelm I have now is it only works for 1 file. Example if I choose 3 files it will print 3 copies of only one of the documents so that tells me it knows I dropped 3 files so how would I pass the 1 variable at a time to the script?

You have been super helpful I've been working on this for days and with your help it at least it is working now

If you're now making a selection of files to print, the best way to manage this is with something like this:

$1 is the shell's built-in for "the first argument passed to this script" ($2 is the second argument, etc). For example:

iMac:Desktop nigel$ echo Hello World
Hello World
iMac:Desktop nigel$
iMac:Desktop nigel$ cat 2words2lines.sh 
#!/bin/bash
# Prints each of two arguments on its own line

echo $1
echo $2
iMac:Desktop nigel$
iMac:Desktop nigel$ ./2words2lines.sh Hello World
Hello
World
iMac:Desktop nigel$ 

That's why it worked later, when you directly replaced $1 with $KMVAR_FileName.

That's a combination of a) timing and b) you using a Global variable for Filename. The triggers happen for each file individually, but very quickly, firing up an instance of your macro for each file dropped:

  • Instance 1 sets FileName to the first file's path
  • Instance 2 sets FileName to the second file's path
  • Instance 3 set FileName to the third file's path

But it takes longer than that for the Instance 1's shell script action to instantiate and run -- by the time it is ready, Instance 3 has set FileName to its own file's path -- so that's what Instance 1 uses.

"Broken demo" showing the values. Re-point the "Folder" trigger to a folder of your choosing then drop three files into the folder and compare the resulting dialogs.

Drop Test Broken.kmmacros (3.8 KB)

Image

...but it's easily fixed by prefixing FileName with Local, so each instance has its own copy:

Drop Test Fixed.kmmacros (3.8 KB)

Image

You can read more about variables and "scope" in this part of the KM manual. But the short version is "use Local variables wherever possible, saving the other types for when you want to share data between instances/macros or require that their value persists beyond the life of the instance".

1 Like