With GNU touch
, you can use touch -d @1634761669.7921917 file
to set the last modification time of a file to the specified epoch time (even with subsecond precision as here).
So you could do in zsh
:
#! /bin/zsh -
ret=0
for file in *-<->.<->.wav; do
t=${file:r} t=${t##*-}
touch -d @$t -- $file || ret=$?
done
exit $ret
If it's really the creation time, often called birth time, as reported by ls -l --time=birth
with recent versions of GNU ls
for instance that you want to change, AFAIK that is not possible on Linux other than changing the clock back to that time and create the file again.
The part below is wrong, it does not change the time in the namespace only as I originally believed. See @Busindre's answer for details.
If on Linux (a recent version¹), you could however only change the clock in a new `time` namespace so as not to affect the system's clock globally.
For instance, with:
sudo unshare --time sh -c 'date -s @1634761669.7921917 && exec cp -a file file.new'
You would create a file.new
copy of file
with a birth time close to @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
The zsh
script above could then be written:
#! /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
(and would need to be run as root
).
Some second thought while revisiting this:
I just realised that causes a potential problem: that unshare --time
hack allows the birth time to be set to some arbitrary time in the past but that also causes the change status time (the one reported by ls -lc
for instance) to be set in the past, to the specified time, plus the time it took to make the copy).
That ctime is not meant to be settable arbitrarily either. By setting it in the past like that, it may break the assumptions that some software may make about those files. For instance a backup software may decide to disregard it because it has a ctime that predates the last backup time.
So it may be better to make sure the ctime is not set in that namespace with a faked clock time, for instance, by only creating the file in the past, but copying its contents in the present:
unshare --time sh -Cc '
umask 77 && date -s "@$1" && : > "$2.new"' sh "$t" "$file" &&
cp -aT -- "$file" "$file.new" &&
mv -f -- "$file.new" "$file"
¹ you need a Linux kernel 5.6 or above and CONFIG_TIME_NS
to be enabled in the kernel and util-linux
2.36 or above.
ls -l
)?asterisk
file name corresponds to the start of the recording. If that's the case, it may make more sense to have the birth time correspond to the start of the call and the last modification time to the end of the call.