zsh: получить имя файла скрипта, вызвавшего функцию

Как внутри функции получить имя файла любого скрипта, вызывающего эту функцию?

В расширении подсказки %x указывает имя файла, определяющего функцию. %N предоставляет имя функции. Как получить имя файла, который вызвал функцию?

Было бы полезно сообщить о времени выполнения каждого из моих сценариев запуска, например:

~/.zshenv:

function start_timer() {
  start_time=$(date +%s.%N)
}
function stop_timer() {
  stop_time=$(date +%s.%N)
  elapsed_time=$((stop_time-start_time))
  echo "$SCRIPTNAME took $elapsed_time seconds"
}
start_timer
# initialize env...
end_timer # "~/.zshenv took 0 seconds"

~/.zshrc:

start_timer
# initialize interactive shell...
end_timer # "~/.zshrc took 2 seconds"

~/.zlogin:

start_timer
# initialize login shell...
end_timer # "~/.zlogin took 2 seconds"

person mgiuffrida    schedule 28.02.2016    source источник
comment
Вот очень похожий вопрос, но также нет реального решения.   -  person Lucas    schedule 15.04.2016


Ответы (2)


По крайней мере, в zsh 5.7.1 переменная ZSH_ARGZERO будет сообщать имя текущего скрипта, даже если функция, внутри которой он вызывается, другая:

$ cat foo
function a_function_in_foo {
    echo "ZSH_ARGZERO=$ZSH_ARGZERO"
}
$ cat bar
source foo
a_function_in_foo
$ zsh bar
ZSH_ARGZERO=bar

Он задокументирован по адресу http://zsh.sourceforge.net/Doc/Release/Parameters.html как

ZSH_ARGZERO

Если zsh был вызван для запуска скрипта, это имя скрипта. В противном случае это имя, используемое для вызова текущей оболочки. Это то же самое, что и значение $0, когда установлена ​​опция POSIX_ARGZERO, но всегда доступно.

person bschlueter    schedule 18.03.2019
comment
В zsh 5.8 с Debian: $ZSH_ARGZERO в функции повторяет zsh, когда скрипт вызывается из terminal, и ~/.vscode/extensions/rogalmic.zsh-debug-0.1.3/zshdb_dir/zshdb при запуске из vscode с расширением zsh-debug. - person Timo; 05.05.2021

Вы можете передать имя в качестве параметра.

~/.zshenv:

function start_timer() {
  echo "File: `basename $@`"             # <----
  start_time=$(date +%s.%N)
}

~/.zshrc:

start_timer $0                           # <----
# initialize interactive shell...
end_timer # "~/.zshrc took 2 seconds"

basename удаляет только все до последней косой черты, если вы хотите показать только имя файла.

Мой тест:

 File: aliases.zsh
 took 0.0018649101257324219 seconds

И - если вы вызываете сценарии самостоятельно, вы также можете использовать time в качестве команды префикса для вывода времени их выполнения.

$ time touch x
touch x  0.00s user 0.00s system 7% cpu 0.019 total
person pommes    schedule 28.02.2016
comment
При инициализации с помощью zsh $0 просто zsh в каждом файле запуска. Это сработало бы, если бы я передал имя скрипта напрямую в функцию, например end_time ${(%):-%x}, но вы можете понять, почему я предпочитаю не использовать это при каждом вызове :) - person mgiuffrida; 28.02.2016