将 zsh 脚本转换为 zsh shell 函数

将 zsh 脚本转换为 zsh shell 函数

我在用如何在 zsh 中定义并加载自己的 shell 函数将我的 zsh 脚本转换为 shell 函数。

脚本我试图转换的是:

#! /bin/zsh -

trap true INT QUIT

zmodload zsh/datetime
TIMEFMT='Total duration: %*E'
strftime -s start 'Start Time: %d/%m/%y %I:%M%P'
{
  duration=$(
    exec 4>&2 2>&1 1>&3 3>&-
    time "$@" 2>&4 4>&-
  )
} 3>&1
ret=$?
strftime -s end 'End Time: %d/%m/%y %I:%M%P'
echo -e
print -rlu2 $start $end $duration
return $ret

因此,我删除了 shebang 并将脚本放入我的fpath.

问题是,它不再显示$duration

% reporttime tail -f ~/.xsession-errors
Cinnamon warning: Log level 128: posix_spawn avoided (fd close requested)
Cinnamon warning: Log level 128: posix_spawn avoided (fd close requested)
Cinnamon warning: Log level 128: posix_spawn avoided (fd close requested)
Cinnamon warning: Log level 128: posix_spawn avoided (fd close requested)
Cinnamon warning: Log level 128: posix_spawn avoided (fd close requested)
Cinnamon warning: Log level 128: posix_spawn avoided (fd close requested)
^C
Start Time: 03/01/21 03:15pm
End Time: 03/01/21 03:15pm

我能做些什么?

答案1

我无法重现你的问题。但是,如果您想使其成为可自动加载函数,则需要将陷阱和变量设置为该函数的本地函数。的输出echo -e也应该像报告的其余部分一样发送到 stderr,或者在调用中添加额外的换行符print

zmodload zsh/datetime

set -o localtraps
trap true INT QUIT

local TIMEFMT='Total duration: %*E' start end ret duration

strftime -s start 'Start Time: %d/%m/%y %I:%M%P'

{
  duration=$(
    exec 4>&2 2>&1 1>&3 3>&-
    time "$@" 2>&4 4>&-
  )
} 3>&1
ret=$?

strftime -s end 'End Time: %d/%m/%y %I:%M%P'
print -rlu2 '' $start $end $duration
return $ret

另一种选择是将整个内容包含在其中,(...)以便它在子 shell 中运行。

请注意,正如您所指的答案中已经提到的,since报告zshtime进程消耗的资源(不仅zsh限于经过的时间和CPU时间,还可以包括内存使用情况、上下文切换、I/O操作.. .),它只能用于在子进程中运行的命令。因此,如果您希望能够使用time某个函数,则需要替换time "$@"time ("$@"),以便该函数在子 shell 进程中运行。

但由于您只对过去时间,而不是真正处理资源,您不妨使用我建议的其他方法,只需手动计算结束时间(并HH:MM:SS.TTT手动进行格式化或使用,strftime如果您愿意的话)。

相关内容