根据文件名更改文件创建日期和时间

根据文件名更改文件创建日期和时间

我正在将 Asterisk 通话录音从我们的主服务器复制到 samba 共享,并且创建日期和时间已更改为当前日期和时间。

文件格式为:in-xxxxxxxxxx-xxxxxxxxxx-20211020-162749-1634761669.7921917.wav

粗体部分为EPOCH时间。我有数百个这样的文件,我需要根据文件名中的 EPOCH 时间戳更改文件的创建日期。谁能帮我?

答案1

使用 GNU touch,您可以使用touch -d @1634761669.7921917 file设置最后修改时间文件到指定纪元时间(即使具有亚秒精度,如下所示)。

所以你可以这样做zsh

#! /bin/zsh -
ret=0
for file in *-<->.<->.wav; do
  t=${file:r} t=${t##*-}
  touch -d @$t -- $file || ret=$?
done
exit $ret

如果真的是创建时间, 通常被称为出生时间ls -l --time=birth,正如最近版本的 GNU所报告的,ls例如您想要更改,据我所知,除了将时钟更改回那个时间并再次创建文件之外,在 Linux 上这是不可能的。


下面的部分是错误的,但确实如此不是仅按照我最初的想法更改命名空间中的时间。看@Busindre 的回答了解详情。

但是,如果在 Linux(最新版本 1)上,您只能更改新“time”命名空间中的时钟,以免全局影响系统时钟。

例如,与:

sudo unshare --time sh -c 'date -s @1634761669.7921917 && exec cp -a file file.new'

您将创建一个file.new副本file出生时间相近@1634761669.7921917

$ sudo unshare --time sh -c 'date -s @1634761669.7921917 && exec cp -a file file.new'
$ ls -l --time=birth --time-style=+%s.%N file file.new
-rw-r--r-- 1 stephane stephane 0 1642699170.474916807 file
-rw-r--r-- 1 stephane stephane 0 1634761669.792191700 file.new

上面的脚本zsh可以写成:

#! /bin/zsh -
ret=0
for file in *-<->.<->.wav; do
  t=${file:r} t=${t##*-}
  
  unshare --time sh -c '
    date -s "@$1" && exec cp -aTn -- "$2" "$2.new"' sh "$t" "$file" &&
    mv -f -- "$file.new" "$file" || ret=$?
done
exit $ret

(并且需要作为 运行root)。

重新审视这一点时又想到了一些:

我刚刚意识到这会导致一个潜在的问题:unshare --time黑客允许将出生时间设置为过去的某个任意时间,但这也会导致改变状态时间(例如报告的那个ls -lc)设置为过去的指定时间,加上制作副本所花费的时间)。

时间也不意味着可以任意设置。通过像这样将其设置为过去,可能会打破某些软件可能对这些文件所做的假设。例如,备份软件可能决定忽略它,因为它的 ctime 早于上次备份时间。

因此,最好确保 ctime 没有在该名称空间中设置为伪造的时钟时间,例如,仅通过创造过去的文件,但复制当前的内容:

unshare --time sh -Cc '
  umask 77 && date -s "@$1" && : > "$2.new"' sh "$t" "$file" &&
  cp -aT -- "$file" "$file.new" &&
  mv -f -- "$file.new" "$file"

¹ 您需要 Linux 内核 5.6 或更高版本,并在内核2.36 或更高版本CONFIG_TIME_NS中启用。util-linux

答案2

时间命名空间 with 的使用unshare不正确。当使用该date命令设置系统日期和时间时,会进行“CLOCK_REALTIME”类型的系统调用。

该系统调用与时间命名空间不兼容,因此,即使unshare -T为了不影响整个操作系统而使用时间命名空间(),它也不会起作用。当使用带有 -T/--time 选项的 unshare 时,在新命名空间中生效的唯一系统调用将是 CLOCK_MONOTONIC/BOOTTIME (示例uptime命令)。

要克隆访问和修改时间,可以使用 touch 的 -r 选项。

touch target_file -r reference_file

相关内容