0

I have a folder (many files and subfolders, a few hundred gigabytes). I duplicated the folder with rsync, but forgot to preserve the timestamps.

The new folder has now had many new files added to it and existing files modified.

I need to copy across the timestamps of the old folder to the new folder, but only if the files haven't been modified after Jul 9 2021.

I don't think rsync will do it. I think I'll have to use touch -t, but need an efficient way to process all the files. Is there a better way? Or, how can I process all the files and update the timestamps if the files haven't been modified since Jul 9.

Thanks.

JamesDuff
  • 101
  • https://unix.stackexchange.com/questions/200408/can-rsync-fix-time-stamps-without-redownloading, https://serverfault.com/questions/344731/rsync-copying-over-timestamps-only – BowlOfRed Jan 20 '22 at 07:50
  • Unfortunately that isn't what I'm looking for. The answer in that post would update ALL the timestamps from the source to the destination. I only want to apply the changes to files that have not been changed since. The scenario given there is a mirror. Mine is two copies, one with newer changes, one with the correct timestamps. – JamesDuff Jan 20 '22 at 09:40
  • 1
    Possible solution: recopy original to a new folder, maintaining timestamp, then copy the other folder on top using either check size or checksum to only overwrite files that have changed. Will write this as a solution if it works. – JamesDuff Jan 20 '22 at 10:59
  • You can use find to limit the ones being used to the "suspect" timestamp. Then you can either feed that file list to rsync or use some of the other techniques to update the timestamp. – BowlOfRed Jan 20 '22 at 16:26

3 Answers3

0

Here's a one-liner that should work:

find /path/to/newdir -type f -not -newermt 09jul2021 -printf './%P\000' | rsync -r --files-from=- -0 --size-only --times /path/to/olddir/ /path/to/newdir/

The first half of the command generates a null-separated list of files in "newdir" that haven't been modified since July 9, 2021 formatted with paths relative to the synced directory.

The second half of the command runs rsync on that list of files and changes their modification timestamps in "newdir" to match the ones in "olddir"

fuzzydrawrings
  • 1,656
  • 5
  • 12
  • It should be noted that it would still retransfer the files that have different size or type between the two directories. You probably don't want the -r which would cause whole directory trees to be transferred if a regular file in newdir happens to be a dir in oldir. – Stéphane Chazelas Jan 22 '22 at 08:57
0

The most reliable way wound up being to use rsync itself.

By copying back onto the old folder with the --size-only flag, only files that were newer than the old folder were copied, thus it didn't affect the timestamps of existing files.

This isn't going to be a perfect answer for everyone, but the risk here of small changs being lost with the --size-only flag are not going to be a problem for me.

I ran it with --dry-run first, then checked the results with diff to make sure things were working as expected.

JamesDuff
  • 101
0

With GNU find/touch.

cd newdir && find . -depth ! -newermt 2021-07-10 -exec \
  touch -hr '../olddir/{}' '{}' \;

(note that 2021-07-10 here means 2021-07-10 at 00:00:00 in the morning, change to ! -newertmt 2021-07-10T23:59:59.99999999 if you want to exclude files last modified at the very nanosecond at midnight).

Note that it runs one touch per file, so won't be efficient.

If you have a busybox configured so that the sh applet can invoke other applets without fork+exec, it can be sped up with:

cd newdir && find . -depth ! -newermt 2021-07-10 -exec \
  busybox sh -c '
    for file do
      touch -hr "../olddir/$file" "$file"
    done' sh {} +

Though beware you need busybox 1.34.0 or newer for its touch applet to also copy the nanosecond part of the timestamps.