Zsh – Absolute Path to Currently Running Shell

processshellzsh

Sometimes the output of ps -p $$ shows the absolute path to the currently-running zsh,

% ps -p $$
  PID TTY           TIME CMD
 1027 ttys005    0:00.11 /usr/local/bin/zsh

but not always:

% ps -p $$
  PID TTY           TIME CMD
 1507 ttys003    0:00.07 zsh -fl

What is a consistent way to get the path to the currently-running zsh?

EDIT (clarification): I'm interested in how to do this primarily in Darwin and Linux, but also in NetBSD.

Best Answer

The CMD output by ps is either the process name or the arguments passed to the command (including the first argument argv[0]). Though it bears some relation with the path of the executable, there's no guarantee for them to be linked.

On Linux:

print -r -- /proc/self/exe(:A)

On Darwin and Linux and possibly others:

lsof -ap"$$" -dtxt  -Fn | sed '2!d;s/.//;q'

But I don't know how reliable it is.

Another heuristic:

print -r -- ${${0#-}:c:A}

$0, like you see in the ps output contains the first argument that zsh received (argv[0]), or when passed a script as argument, that argument.

In the first case, typically, (by convention, there's no guarantee) that argv[0] would be either a path including a / (relative or absolute), or zsh (something without /) in which case the caller will have looked up zsh in his $PATH or his command hash table... If the path is relative, the above method will only work if the current directory has not changed since zsh was invoked. If there's no /, the method will only work if zsh is looking up the executable the same way as the caller did.

In the case of a script, it's the path of the script that will be returned instead of that of the interpreter (contrary to the first two solutions).

Related Question