在bash脚本中创建时间戳变量

Dan*_*Dan 338 variables bash timestamp

我正在尝试在shell脚本中创建一个时间戳变量,以使日志记录更容易一些.我想在脚本的开头创建变量,并在每次发出时打印出当前时间echo $timestamp.事实证明,这比我想象的要困难得多.以下是我尝试过的一些事情:

timestamp="(date +"%T")" echo打印出来 (date +"%T")

timestamp="$(date +"%T")" echo打印变量初始化的时间.

我尝试过的其他事情只是轻微的变化,没有任何改善.有谁知道如何完成我想要做的事情?

dch*_*rov 523

如果你想获得unix时间戳,那么你需要使用:

timestamp=$(date +%s)
Run Code Online (Sandbox Code Playgroud)

%T会给你一点时间; 与%H:%M:%S(通过http://www.cyberciti.biz/faq/linux-unix-formatting-dates-for-display/相同)

  • 我想这会得到很多赞成,因为它回答了问题的标题,但它没有回答问题正文:D OP希望每次都得到一个不同的时间戳,而这将为整个脚本存储一个. (8认同)
  • 但是这个变量只会保存变量启动时的值,对吗? (5认同)
  • 我来这里正是为了寻找这个。即从“date”获取unix时间戳的正确格式字符串。不过,我也赞成“正确”答案。我并不是在寻找这个,但它是对原始问题的更好答案,而且对我来说也非常有用。 (3认同)

gio*_*ano 274

为了获得当前时间戳而不是定义固定变量的时间,诀窍是使用函数而不是变量:

#!/bin/bash

# Define a timestamp function
timestamp() {
  date +"%T"
}

# do something...
timestamp # print timestamp
# do something else...
timestamp # print another timestamp
# continue...
Run Code Online (Sandbox Code Playgroud)

如果您不喜欢%T说明符给出的格式,则可以组合接受的其他时间转换说明符date.对于GNU date,您可以在官方文档中找到这些说明符的完整列表:https://www.gnu.org/software/coreutils/manual/html_node/Time-conversion-specifiers.html#Time-conversion-specifiers

  • 对我来说,我想要'date +"%Y-%m-%d_%H-%M-%S"` (149认同)
  • 根据你打算如何使用它,你仍然需要使用命令替换:`echo"$(timestamp):发生的事情"`. (23认同)
  • 至于格式化,这里有一套最常用的格式:http://zxq9.com/archives/795 (5认同)
  • 我想很多人都会在这个问题上找到一种方法来生成一个unix时间戳(正如我所知)并找到dchakarov的答案更有用,即使这个答案能更好地解决提问者的问题. (5认同)
  • 由于某种原因,这并没有给我时间戳,而是当前时间与":"之间. (3认同)
  • 很高兴知道为什么有人认为这个答案是错误的:6张赞成票,但没人愿意解释原因。通过阅读问题,我真的看不出答案有什么问题。 (2认同)

Ins*_*ein 237

您可以参考下表生成各种格式的时间戳:

格式/结果 命令 输出
年-月-日 date -I $(date -I)
YYYY-MM-DD_时:分:秒 date +%F_%T $(date +%F_%T)
YYYYMMDD_hhmmss date +%Y%m%d_%H%M%S $(date +%Y%m%d_%H%M%S)
YYYYMMDD_hhmmss(UTC 版本) date --utc +%Y%m%d_%H%M%SZ $(date --utc +%Y%m%d_%H%M%SZ)
YYYYMMDD_hhmmss(带有本地 TZ) date +%Y%m%d_%H%M%S%Z $(date +%Y%m%d_%H%M%S%Z)
YYYYMMSShhmmss date +%Y%m%d%H%M%S $(date +%Y%m%d%H%M%S)
YYYYMMSShhmmssnnnnnnnnn date +%Y%m%d%H%M%S%N $(date +%Y%m%d%H%M%S%N)
YYMMDD_hhmmss date +%y%m%d_%H%M%S $(date +%y%m%d_%H%M%S)
自 UNIX 纪元以来的秒数 date +%s $(date +%s)
仅纳秒 date +%N $(date +%N)
自 UNIX 纪元以来的纳秒 date +%s%N $(date +%s%N)
ISO8601 UTC 时间戳 date --utc +%FT%TZ $(date --utc +%FT%TZ)
ISO8601 UTC 时间戳 + 毫秒 date --utc +%FT%T.%3NZ $(date --utc +%FT%T.%3NZ)
ISO8601 本地 TZ 时间戳 date +%FT%T%Z $(date +%FT%T%Z)
YYYY-MM-DD(短日) date +%F\(%a\) $(date +%F\(%a\))
YYYY-MM-DD(长日) date +%F\(%A\) $(date +%F\(%A\))

  • 我很少需要滚动浏览其他 11 个答案才能找到最好的答案。:) (31认同)
  • 注意`date -I`,它在macos bash或zsh上不起作用。不过非常有用的答案。 (2认同)

Gir*_*ore 56

DATE=`date "+%Y%m%d"`

DATE_WITH_TIME=`date "+%Y%m%d-%H%M%S"` #add %3N as we want millisecond too
Run Code Online (Sandbox Code Playgroud)

  • +1 用于添加毫秒部分。这个 `echo $(date +"%Y-%m-%dT%T.%3N%z")` 但是我不能让它在 Mac 终端上工作。如何在 Mac 中做同样的事情。谢谢 (2认同)

Can*_*ner 31

ISO 8601格式(2018-12-23T12:34:56)比UNIX时间戳更具可读性.但是在某些操作系统上,您不能拥有:文件名.因此,我建议使用类似的东西:

2018-12-23_12-34-56
Run Code Online (Sandbox Code Playgroud)

您可以使用以下命令以此格式获取时间戳:

TIMESTAMP=`date +%Y-%m-%d_%H-%M-%S`
Run Code Online (Sandbox Code Playgroud)

这是我见过许多应用程序使用的格式.另一个好处是,如果你的文件名以此开头,你可以按字母顺序对它们进行排序,它们将按日期排序.

  • `TZ=UTC date +...` 可以通过使用 UTC 时间戳使其更加便携 (2认同)

Chr*_*sen 26

对于我的欧洲同胞,请尝试使用以下方法:

timestamp=$(date +%d-%m-%Y_%H-%M-%S)
Run Code Online (Sandbox Code Playgroud)

将给出格式的格式:“15-02-2020_19-21-58”

您调用变量并获得这样的字符串表示

$timestamp
Run Code Online (Sandbox Code Playgroud)

  • 作为一个欧洲人,我一生中从未使用过“DD-MM-YYYY”,总是用“YYYY-MM-DD”来表示所有事情。这与在文档中写入“2022 年 6 月 22 日”不同,但从数字上看,它从来不是“22-06-2022”,而始终是“2022-06-22”。只是说。 (2认同)

cho*_*oba 15

使用命令替换:

timestamp=$( date +%T )
Run Code Online (Sandbox Code Playgroud)

  • @ dan08:这就是变量的工作原理.如果需要动态输出,请使用函数. (10认同)
  • 这是我已经尝试过的,它只打印出变量初始化的时间. (3认同)

小智 14

我正在使用ubuntu 14.04.

我系统中的正确方法应该是date +%s.

输出date +%T就像12:25:25.


Loï*_*oïc 11

很多答案,但找不到我要找的东西:

date +"%s.%3N"
Run Code Online (Sandbox Code Playgroud)

返回类似: 1606297368.210

  • 在 MacOS 上,内置的“日期”不支持“%N”格式;请参阅 /sf/answers/2354909581/。 (2认同)
  • 是的,有很多答案,其中大多数都是错误的,因为人们显然没有阅读这个问题 (2认同)

小智 10

您可以使用

timestamp=`date --rfc-3339=seconds`
Run Code Online (Sandbox Code Playgroud)

这提供了格式 2014-02-01 15:12:35-05:00

back-tick(`)字符将导致它们之间的内容被评估并将结果包含在该行中. date --help有其他选择.

  • 由于输出中的空间,这不是理想的时间戳格式.一定要在使用中引用它"$ timestamp",否则你会得到两个参数.例如`touch $ timestamp`将产生两个文件. (2认同)

F. *_*uri 8

bash可以原生显示以微秒为单位的时间!

1.避免分叉!!!

必须为每个记录的行运行date是多余的!

尽可能使用 bash 的内置函数。

在提出这个问题时,版本是 bash-4.2。

在此版本中,打印当前时间的纯 bash 方式是:

printf '%(%T)T\n' -1
Run Code Online (Sandbox Code Playgroud)

或者

printf '%(%T)T\n' -1
Run Code Online (Sandbox Code Playgroud)

因此,每行带有时间戳的简短函数登录可以是:

logLine() {
    printf '%(%T)T %s\n' -1 "$*"
}
Run Code Online (Sandbox Code Playgroud)

然后

$ logLine Hello world.
10:11:32 Hello world.
Run Code Online (Sandbox Code Playgroud)

2. 时间以秒为单位,使用printf内置:

要将当前时间存储到变量中,您将使用:

printf -v varname '%(%T)T' -1
Run Code Online (Sandbox Code Playgroud)

或存储(可重用)UNIX EPOCH

printf -v varname '%(%s)T' -1
Run Code Online (Sandbox Code Playgroud)

然后

printf 'Stored time stamp is: %(%c)T\n' "$varname"
Stored time stamp is: Sat Jan 27 04:26:00 2018
Run Code Online (Sandbox Code Playgroud)

2.1 时间以秒为单位,使用$EPOCHSECONDS伪变量

从 bash 5.0-alpha 版本(2018-05-22)开始,我们可以使用两个变量:$EPOCHSECONDS$EPOCHREALTIME

printf '%(%T)T\n' -1
Run Code Online (Sandbox Code Playgroud)
printf '%(%T)T\n' -1
Run Code Online (Sandbox Code Playgroud)
logLine() {
    printf '%(%T)T %s\n' -1 "$*"
}
Run Code Online (Sandbox Code Playgroud)

示例:睡到下一分钟

$ logLine Hello world.
10:11:32 Hello world.
Run Code Online (Sandbox Code Playgroud)

3. EPOCH时间扩展。

本机的 printf 可以UNIX EPOCH SECONDS通过经典date规则进行扩展。请参阅:man -P'less +/^\ *FORMAT' date或看看Instein 的回答

printf -v varname '%(%T)T' -1
Run Code Online (Sandbox Code Playgroud)

具有避免 fork 设置变量的巨大优势:

printf -v varname '%(%s)T' -1
Run Code Online (Sandbox Code Playgroud)
printf 'Stored time stamp is: %(%c)T\n' "$varname"
Stored time stamp is: Sat Jan 27 04:26:00 2018
Run Code Online (Sandbox Code Playgroud)

4.关于微秒

今天,我使用bash >= 5.1.4 ...

从 bash 5.0-alpha 版本开始,(2018-05-22):

b. 有一个 EPOCHSECONDS 变量,它扩展为自 Unix 纪元以来的秒数。

C。有一个 EPOCHREALTIME 变量,它以微秒粒度扩展为自 Unix 纪元以来的以秒为单位的时间。

因此,如果您想使用微秒粒度,函数可以变为:

man -P'less +/EPOCH' bash
Run Code Online (Sandbox Code Playgroud)

然后

EPOCHREALTIME
       Each time this parameter is referenced, it expands to the number
       of  seconds  since  the  Unix  Epoch (see time(3)) as a floating
       point  value  with  micro-second  granularity.   Assignments  to
       EPOCHREALTIME  are ignored.  If EPOCHREALTIME is unset, it loses
       its special properties, even if it is subsequently reset.
EPOCHSECONDS
       Each time this parameter is referenced, it expands to the number
       of  seconds  since the Unix Epoch (see time(3)).  Assignments to
       EPOCHSECONDS are ignored.  If EPOCHSECONDS is  unset,  it  loses
       its special properties, even if it is subsequently reset.
Run Code Online (Sandbox Code Playgroud)

睡到下一分钟变得有点复杂,因为无法计算数:

echo $EPOCHSECONDS
1692818546
myvar=$EPOCHSECONDS
echo $myvar
1692818547
Run Code Online (Sandbox Code Playgroud)

$EPOCHREALTIME使用前储存

重要提示:但是要小心!_两个变量的扩展方式不同!请参阅:不要混合 EPOCHREALTIME 和 EPOCHSECONDS!

避免扩展$EPOCHREALTIME两次以分隔整数小数部分:

不要这样做:

sleep $((60-EPOCHSECONDS%60));printf '%(%T)T\n' -1
21:26:00
Run Code Online (Sandbox Code Playgroud)

但确保只扩展$EPOCHREALTIME一次并同时拆分它们:

printf '%(%A %d %B %Y, %H:%M)T\n' $EPOCHSECONDS
Friday 24 November 2023, 09:21
Run Code Online (Sandbox Code Playgroud)

所以你可以:

printf '%(%a %d %T)T.%s\n' $nowSec $nowMus
Fri 24 09:31:00.166914
Run Code Online (Sandbox Code Playgroud)

或者甚至减少数字或小数:

printf -v nowMus %.3f .$nowMus
printf '%(%a %d %T)T.%s\n' $nowSec ${nowMus#*.}
Fri 24 09:31:00.167
Run Code Online (Sandbox Code Playgroud)


che*_*ner 6

最新版本的bash不需要调用外部程序date

printf -v timestamp '%(%T)T'
Run Code Online (Sandbox Code Playgroud)

%(...)T使用相应的参数作为UNIX时间戳,并根据strftime括号之间的-style格式对其进行格式化。参数-1对应于当前时间,并且在没有歧义的情况下可以省略。


Jon*_*n L 6

GNU bash 的时间戳格式化技巧,版本 4.4.20(1)-release (x86_64-pc-linux-gnu)

 echo "$(date +%Y-%m-%d_%H:%M:%S.%6N) Info >>> enter main"
Run Code Online (Sandbox Code Playgroud)

输出:

 2023-01-08_23:08:48.013592 Info >>> enter main
Run Code Online (Sandbox Code Playgroud)

如果您想用空格替换 '_',请执行以下操作(没有 '\' 收到错误消息)

 echo "$(date +%Y-%m-%d\ %H:%M:%S.%6N) Info >>> enter main"
 echo "$(date +%Y-%m-%d\ %T.%6N) Info >>> enter main"
Run Code Online (Sandbox Code Playgroud)

输出:

 2023-01-08 23:10:40.692674 Info >>> enter main
Run Code Online (Sandbox Code Playgroud)


小智 5

timestamp=$(awk 'BEGIN {srand(); print srand()}')
Run Code Online (Sandbox Code Playgroud)

没有值的 srand 在大多数 awk 实现中使用当前时间戳。

  • fwiw,对性能感到好奇:以下打印相同: (1) `awk '....'` (如上所示);(2) `日期'+%s'`; (3) `printf '%(%s)T'`; 按性能提高的顺序列出:在我的系统上,“date”大约比“awk”快 2 倍;`printf` 比 `date` 快 50 倍以上,比 `awk` 快 100 倍。 (2认同)