How to get real cmd line from Execute Shell action

I always use log.txt to track serious work KM does.
And sometimes I want to log what happened in Execute Shell action.
What I did is like this:


But in log.txt. What is logged is like this:
————
20241020 - 134234

"$KMVAR_FFmpeg____PATH" -sseof -0.5 -i "$KMVAR_Local__Input_Video_Path" -vsync 0 -q:v 31 -update true "$KMVAR_Local__NewName_FullPath"
————
The variable token was not processed.
So I want to know if I have a way to do this.
KDM ? - get cmd line in execute shell action.kmmacros (3.7 KB)

I think I can make subroutine to convert
$KMVAR_Local__NewName_FullPath
to
Local__NewName_FullPath
to
%Variable%Local__NewName_FullPath%

with this way convert entire line to real one. But it takes a lot of time, inputs, So I think maybe someone here know smarter way to do this.

...is the form you use to access KM variables in your shell script.

Your "Append" action is a standard KM action, so you should use the usual variable tokens there:

%Variable%FFmpeg____PATH% -sseof -0.5 -i %Variable%Local__Input_Video_Path% -vsync 0 -q:v 31 -update true %Variable%Local__NewName_FullPath%

I konw I can do this. But I don't want to do it in this way.
NOT a programming way.
I said I can make a subroutine convert
cmd line in shell action
to
cmd line in real world
But still looks not smart.

Then perhaps you are asking the wrong question?

Do you actually mean "I would like to write to the log file as part of the shell script, not as a separate KM action"?

If you don't mean that then please explain why you want to do this. As written, your KMVAR_... variables, which are exports of your KM variables that only exist in the executing instance of your shell script, don't get changed within the shell script -- there's no point in getting those values rather than the KM variable's values.

If they do change and you want the "updated" values for later in your macro you are going to have to rethink things because your shell script is asynchronous and can't directly return values to KM. You'll need to write out the values to a text file, use osascript to post them back to KM global variables, or similar.

Sorry for my English.
In my example above. The real cmd line run in shell should be
"AAAAAA" -sseof -0.5 -i "BBBBBB" -vsync 0 -q:v 31 -update true "CCCCCC"
I want to see this in my log.txt.
But for now, it looks like KM doestn't process shell-style-token like "$KMVAR_FFmpeg____PATH".
And I thought I can write a subroutine to filter shell-style-token in Shell cmd line. Convert it into real cmd line.
But I need pass unknown variables in and out of sub. So the sub plan dropped.
For Now
I get this
image
I can use this to get what I want. But it is really heavy and ugly. I dont want to use it.
KDM ? - get cmd line in execute shell action.kmmacros (8.7 KB)

If we open terminal, we can hit uparrow to see the last cmd line run on it.
So i think there must be easier way to do this. to see what happened in SHELL.

Please read this part of the "Execute a Shell Script" Wiki page so you can understand how KM variables are passed to the shell.

Simplistically:

  1. KM instantiates a new shell
  2. KM creates "environment variables" in the new shell, naming them KMVAR_ plus the name of the variable in KM
  3. The value of each environment variable is set to the value of the corresponding KM variable
  4. The environment variables are destroyed along with the rest of the shell instance when the script terminates

So KMVAR_FFmpeg____PATH is a copy of your KM variable FFmpeg____PATH and holds the same value as FFmpeg____PATH held at the moment the shell was instantiated. You can change that value within the shell instance but it will not change the value stored in the KM variable.

If you want to log the environment variable values you need to do it within their shell script. So your shell script action would be something like:

#!/bin/bash
"${KMVAR_FFmpeg____PATH}" -sseof -0.5 -i "${KMVAR_Local_Input__Video_Path}" -vsync 0 -q:v 31 -update true "${KMVAR_Local__NewName_FullPath}"
echo -e "----\n"$(date "+%Y%m%d - %H%M%S")"\n\n${KMVAR_FFmpeg____PATH} -sseof -0.5 -i ${KMVAR_Local_Input__Video_Path} -vsync 0 -q:v 31 -update true ${KMVAR_Local__NewName_FullPath}\n----" >> /Users/chris/Downloads/log__$(date "+%Y%M%d").txt

(Not tested, so check carefully -- especially the number of underscores used.)

Terminal is an interactive shell, a KM shell script is non-interactive. The two have different behaviours -- one of them is that interactive shells have a history and you can recall previous commands, non-interactive shells do not.

Don't assume that something you can do in the Terminal can also be done in a KM shell script. The two environments are very different.

This is something completely different -- effectively "for a string that contains shell-environment formatted names, try to get the values of the associated KM variables".

"Try" is important as you have no way of knowing if a _ in a name is a literal _ or an automatic replacement for a space character.

And it is a completely different problem. You know what variables are used in your shell script so there's no need to jump through hoops -- just reference them in KM in the "normal" way.

If you have an example macro that is running a shell script that uses "unknown" (to the macro) KM variables and which can't be derived from actions in the macro itself, post it. Then we'll all be looking at the same problem instead of a macro that doesn't have the problem at all.

you need to do it within their shell script

perfect. This is the point.
This is enough for me. Many Many thanks.

#!/bin/bash
"${KMVAR_FFmpeg____PATH}" -sseof -0.5 -i "${KMVAR_Local_Input__Video_Path}" -vsync 0 -q:v 31 -update true "${KMVAR_Local__NewName_FullPath}"
echo -e "----\n"$(date "+%Y%m%d - %H%M%S")"\n\n${KMVAR_FFmpeg____PATH} -sseof -0.5 -i ${KMVAR_Local_Input__Video_Path} -vsync 0 -q:v 31 -update true ${KMVAR_Local__NewName_FullPath}\n----" >> /Users/chris/Downloads/log__$(date "+%Y%M%d").txt

this works on my mac. But I know nothing about bash. So I just give some edit to make it work in normal KM execute shell action.

"$KMVAR_FFmpeg____PATH" -sseof -0.5 -i "$KMVAR_Local__Input_Video_Path" -vsync 0 -q:v 31 -update true "$KMVAR_Local__NewName_FullPath"
echo "----\n\n$KMVAR_FFmpeg____PATH -sseof -0.5 -i $KMVAR_Local__Input_Video_Path -vsync 0 -q:v 31 -update true $KMVAR_Local__NewName_FullPath\n----" >> /Users/chris/Downloads/log.txt

this works on my system.
And go further. If I apply this method, I need to input cmd line in Execute Shell action always in this way. To make it simpler, I build a macro to do this:
image
kme Execute Shell - Copy All > fiter CMD > echo > write in > Paste v0.kmmacros (10.0 KB)

So the workflow for me is:

step 1:
input cmd line in Execute Shell action
step 2:
hit hotkey to trigger the macro which will convert the cmd line into echo > write in format

I still think we add strange thing into the Execute Shell action square. Conflict to the simplism.
But It's enough at some level.

Remember that this means you are using the sh shell -- that's why you had to change the command, the echo command behaves differently in bash and sh.

You are probably using zsh in Terminal, so you might want to start all your KM shell scripts with

#!/bin/zsh

...so you can use the same commands as in Terminal. There will still be differences because

  1. It will be a non-interactive session, not Terminal's interactive session
  2. The shell's "environment" won't be the same, particularly $PATH (unless you've set the KM variable ENV_PATH to the same as your Terminal's $PATH), but also some settings and ALIASes set in your various .profile files that get read in when Terminal starts a session

It really is just down to how a non-interactive shell works and the way it must be instantiated from another process such as KM. In Terminal itself, with its history, it is much easier:

echo "This is a test"
fc -ln -1 >> ~/Desktop/logfile.txt

Actually, thinking about this further (and apologies for this "stream of consciousness"), can you try this action in a test macro? If it works for you, adding the set... line near the start of your script and the fc... line at the end will be a lot easier than duplicating the whole command in an echo:

Log Last Command from a Shell Script.kmactions (1.0 KB)

Log Last Command from a Shell Script.kmactions
This doesn't work on my system. But your new post makes me understand more things.
the below pic:
image
Actually I can use this way to pass the real cmd line out of Execute Shell action. Then I can use KM way to log it.
But not easier than just do it in shell (method-A):

"$KMVAR_FFmpeg____PATH" -i "$KMVAR_Local__Input_Video_Path" -frames:v 1 -y "$KMVAR_Local__NewName_FullPath"
echo "\n----\n\n$KMVAR_FFmpeg____PATH -i $KMVAR_Local__Input_Video_Path -frames:v 1 -y $KMVAR_Local__NewName_FullPath\n----\n\n" >> ~/Desktop/logfile.txt

And according to your new direction, I tried some ways about echo last command line in shell. I success with some. For example:

trap 'previous_command=$this_command; this_command=$BASH_COMMAND' DEBUG
"$KMVAR_FFmpeg____PATH" -i "$KMVAR_Local__Input_Video_Path" -frames:v 1 -y "$KMVAR_Local__NewName_FullPath"
echo "$previous_command" >> ~/Desktop/logfile.txt

But what's logged is
"$KMVAR_FFmpeg____PATH" -i "$KMVAR_Local__Input_Video_Path" -frames:v 1 -y "$KMVAR_Local__NewName_FullPath"
the variable staill was not replaced by its value. Not what I want.
So method-A is still my best choice.

I think you found one of the pages I did! I skipped that one because it looked a bit scary...

But yes, I see what you mean. That one, and my suggestion before, print the literal command without any variable expansion. Obvious really, if I'd thought about it more. Sorry for that.

1 Like