通过 bash 给出结束时间的终端计时器

通过 bash 给出结束时间的终端计时器

所以我想到制作一个 bash 函数,以 hh:mm:ss (24 小时格式)接收时间,并制作一个计时器直到那个时间

有点像一次性闹钟,同时还显示还剩多少时间

我正在考虑使用watch命令来完成此任务

我对如何执行此操作有一些疑问,

首先,我如何使用 bash 来知道在某个时间之前还剩下多少?

那么如何将其转换为人类可读的格式以回显到屏幕上?

另外,我怎样才能在过去或将来的另一天执行此操作?

请帮助我创建这个函数,我将在这里发布最终结果,以便每个人都可以使用它。

编辑:我设法从关联@terdon 发布

timer () 
{ 
    start="$(date +%s -d $1)";
    while [ "$start" -ge $(date +%s) ]; do
        days="$(($(($(( $start - $(date +%s) )) * 1 )) / 86400))";
        time="$(( $start - `date +%s` ))";
        if [ $days -gt 0 ]; then
            printf '%s day(s) and %s\r' "$days" "$(date -u -d "@$time" +%H:%M:%S)";
        else
            printf '%s\r' "$(date -u -d "@$time" +%H:%M:%S)";
        fi;
        sleep 0.1;
    done
}

我遇到了一个问题,即使所有参数都在引号内, date -d $1 也无法接受多字参数。我使用 ubuntu 并且使用 bash,这是我运行来进行测试的代码。正如你所看到的,它会忽略第一个单词后面的内容,不带引号,而带引号时,它会给出错误。

$ timer 17:25
00:04:37
$ timer sun
1 day(s) and 06:39:31
$ timer sun 17:25
1 day(s) and 06:39:20
$ timer sun 22:25
1 day(s) and 06:39:09
$ timer "sun 22:25"
date: extra operand ‘22:25’
Try 'date --help' for more information.
bash: [: : integer expression expected

答案1

使用 -d 选项时,您似乎遇到了将多字参数传递给 date 命令的问题。要解决此问题,您可以使用 IFS(内部字段分隔符)变量临时更改 shell 在解析参数时使用的分隔符。以下是如何修改函数以处理多字参数的示例:

timer () 
{ 
    IFS=":" read -ra time_parts <<< "$1"
    time_str=""
    for part in "${time_parts[@]}"; do
        time_str+=" $part"
    done
    start="$(date +%s -d "$time_str")";
    while [ "$start" -ge $(date +%s) ]; do
        days="$(($(($(( $start - $(date +%s) )) * 1 )) / 86400))";
        time="$(( $start - `date +%s` ))";
        if [ $days -gt 0 ]; then
            printf '%s day(s) and %s\r' "$days" "$(date -u -d "@$time" +%H:%M:%S)";
        else
            printf '%s\r' "$(date -u -d "@$time" +%H:%M:%S)";
        fi;
        sleep 0.1;
    done
}

这应该允许您将多字参数传递给函数,例如“sun 22:25”,并让 date 命令正确解析它们。

关于您问的其他问题,您可以使用命令 date -d 来了解距离某个时间还剩多少时间,然后使用该命令

日期 -u -d "@$time" +%H:%M:%S

将其转换为人类可读的格式。

如果您想在过去或将来的另一天执行此操作,您也可以添加日期,例如

日期 -u -d "2022-12-25 22:25" +%s

这将为您提供您提供的日期和时间的时间戳。

相关内容