How can I restore file timestamps of video recordings using the embedded metadata?

Thanks to Warren for informing me about the mediainfo command in his partial answer.

I managed to construct a command that achieved the restoration of timestamps. It loops over the applicable files, and for each file, mediainfo reads the metadata, grep and sed select and format the timestamp, and touch applies it.

for file in *.mp4; do touch -t "$(mediainfo "$file" | grep -m 1 'Tagged date' | sed -r 's/.*([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2}).*/\1\2\3\4\5.\6/')" "$file"; done

The ‘select and format’ part could no doubt be a lot shorter/better; it looks cumbersome to me but I'm not fluent with regexs. Nevertheless, the command worked perfectly. I think I've quoted everything correctly, so it should work with any filename. It may not work if mediainfo outputs a different format but it's easily adaptable.

For example, here is a regex that correctly matches both the format of output from my *.mp4 files such as UTC 2013-11-15 11:36:06, and additionally the format of Warren's example of 2014-2-23T09:00:00Z from my.mov:

's/-/-0/g; s/.*([0-9]{4})-0?([0-9]{2})-0?([0-9]{2})[T ]([0-9]{2}):([0-9]{2}):([0-9]{2}).*/\1\2\3\4\5.\6/'

And apart from mediainfo which I actually had to install manually due to it not being in my distro's repositories (though it looks like newer releases now package it), it should be fairly portable and useful to others if they encounter a similar problem.

Note: Remember to check timezones. According to the GNU info pages, touch, date, and other GNU utilities use the TZ environment variable if set and the ‘system default rules’ otherwise. To see the timezone offset that'll be used, issue:

date +%:::z

To change it, set the TZ environment variable:

export TZ="UTC0"

If the video's timestamps are correct, and are correctly represented (i.e. the time value w.r.t. the timezone represents the correct point in time), then you should make sure that date +%:::z outputs the matching offset for the timestamp's timezone before running touch -t over those files (as above). Use stat to check the files, as it shows the time offset (like date +%:::z).


You can use MediaInfo for that:

$ mediainfo my.mov | grep 'Recorded date'
Recorded date                            : 2014-2-23T09:00:00Z

Getting from that date format to a touch command should be a small matter of programming. Personally, I'd use Perl's Date::Manip module for this. It can almost cope with the above format; it requires 2-digit months with zero padding to understand this particular date format. Fixing that only requires a trivial regexp, which is of course easy in Perl.

$ perl -M'Date::Manip' -e 'print ParseDate("2014-02-23T09:00:00Z")'
2014022302:00:00

The fact that it prints shows that it's parsing. If you drop the 0, you'll see that it doesn't print anything, because ParseDate() returns undef.