我正在将 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 的回答了解详情。
例如,与:
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