4

I was copying Asterisk call recordings from our main server to a samba share and the creation date and times were changed to the current date and time.

The file format is: in-xxxxxxxxxx-xxxxxxxxxx-20211020-162749-1634761669.7921917.wav

The bold part is in EPOCH time. I have hundreds of these files and I need to change the creation date of the file based on that EPOCH time stamp in the file's name. Can anyone help me?

3
  • 2
    By creation date, do you mean the last modification time of the file (the one reported by ls -l)? Commented Jan 20, 2022 at 17:05
  • yes, thanks for the reply Commented Jan 20, 2022 at 17:56
  • I suspect that timestamp in the 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. Commented Jan 20, 2022 at 18:39

2 Answers 2

11

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.

2
  • my version of unshare doesnt have the --time option. unshare from util-linux 2.33.1. I get the following message when trying to run that command. unshare: unrecognized option '--time' Try 'unshare --help' for more information. Commented Jan 20, 2022 at 17:53
  • I was able to use the zsh and touch option you post above, Thank you for your help! Commented Jan 20, 2022 at 18:27
1

The use of the time namespace with unshare is not correct. When using the date command to set the system date and time, a system call of type "CLOCK_REALTIME" is made.

This systemcall is not compatible with the time namespace and therefore, even if a time namespace (unshare -T) is used with the intention of not impacting the entire operating system, it will not work. When using unshare with the -T/--time option, the only system calls that would take effect in the new namespace would be CLOCK_MONOTONIC/BOOTTIME (example uptime command).

To clone the access and modification times, the -r option of touch can be used.

touch target_file -r reference_file
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .