Ok, I think I have a clue what is going on.
The behaviour you are observing in zsh and bash when executing echo $(mc)
is caused by mc
.
When you run mc
normally, it doesn't react when Ctrl+c is pressed, since it ignores SIGINT
. The way to end mc
is by pressing F10 and Enter.
When you run echo $(mc)
the input goes to the mc
process, so it is no wonder that when you press Ctrl+c nothing will happen, because mc
ignores SIGINT
.
But when you run echo $(mc)
and press F10 and Enter it will react.
(When I then press F10 and Enter again it actually quits; it should quit at the first try but I have no idea why it does not.)
From this fact I deduce that Midnight Commander is running normally, but the output from it is put into the shell buffer, so it can later be used by echo
.
Something we should consider normal.
Also you think that bash and zsh are hanging, but I would say that they are not hanging but waiting for the echo
command to return.
But echo
can only return when mc
returns, which it only does when F10 and Enter are pressed.
With this we can also explain what happens when you press Ctrl+z.
By pressing the combination mc
goes to sleep like it would if you had run mc
normally and echo
is still waiting for the sleeping mc
.
So everything is normal behavior.
Except for what fish does.
fish seems to start commands run with echo ($command)
in the background.
It kind of makes sense, since such a command normally does not need any input.
For the why and how I have no answer.
But you can see that it runs in the background when you enter
echo (mc)
jobs
Things that may help you:
The preexec
hook function is called before every command line is executed (not before every command).
preexec() echo will execute: $1
precmd
before each prompt.
precmd() echo executed: $history[$[HISTCMD-1]]
You can extend a function like this:
functions[git]='
(){ '$functions[git]'; } "$@"; local myret=$?
do-extra-stuff
return $myret'
Or:
functions[git-old]=$functions[git]
git() {
git-old "$@"
local myret=$?
do-extra-stuff || return $myret
}
The DEBUG
trap is executed after each command:
trap 'echo $ZSH_DEBUG_CMD returned with $?' DEBUG
You can redefine the accept-line
widget (mapped to Enter) to do stuff in there:
accept-line() {
zle -R "going to run: $BUFFER"
sleep 1
zle .$WIDGET
}
zle -N accept-line
Best Answer
Use
type
infish
like in Bourne-like shell:Or to limit to executables in
$PATH
(ignoring functions, builtins):See also Why not use “which”? What to use then?