64

Currently I have two directories A/ and B/ which are identical in every respect, with the exception of the timestamps. Therefore if I run the command :

rsync --dry-run -crvv A/ B/

then all files are marked "uptodate", whereas the command :

rsync --dry-run -rvv A/ B/

shows that all files are to be copied over from A/ to B/.

My question is this : given that I know the files are identical (in respect to contents), then is there any way (via rsync or otherwise) to set the timestamps for files in B/ to be identical to the timestamps of the files in A/, without copying over all the files from A/ to B/ ?

Thanks

3
  • If you know the files are identical, then why must you go out of your way to not copy over them to get the date/time stamp you require?
    – Tim
    Dec 28, 2011 at 16:54
  • 5
    @Tim: maybe there's a lot of data.
    – Richard
    May 24, 2016 at 3:14
  • @Tim Today I just spent an entire day migrating over 300 GB of data over a slow network. When sftp finished, it was already midnight. It was only during my final check using ls and stat that I realized I lost all the timestamps (forgot to use sftp -p!) They are important for me to identify the history of the files. I was saved by the answer, rsync -vrt --size-only only took 60 seconds to run! Dec 20, 2020 at 19:30

8 Answers 8

103

Using -t (preserve timestamps) and --size-only will only compare files on size. If the size matches, rsync will not copy the file but since -t is specified, it will update the timestamp on the destination file without recopying it.

Make sure to not use -u (update) as this will skip files that already exist and completely skip updating the timestamp.

I had the problem of originally not using rsync to copy a bunch of files to a new drive, and therefore the timestamps were updated to current time. I used the command below to sync everything correctly in a decent amount of time:

rsync -vrt --size-only /src /dest
3
  • 6
    I also suggest adding --existing to prevent accidental copies of new files.
    – leden
    Mar 26, 2016 at 23:15
  • 2
    The flag --archive (or -a) includes -r, -t and more :)
    – Dor
    Mar 19, 2017 at 14:15
  • prefer this answer since rsync works over remotes also
    – troseman
    Aug 19, 2020 at 21:11
8

Using --size-only will cause rsync to skip comparing file timestamps (and therefore file contents) if the sizes match. Combining this with --times will clone the timestamps across to the target tree.

1
  • Adding --checksum on top of that should take care of files with the same size but different contents.
    – user1602
    Sep 21, 2021 at 8:04
4

Use the source (e.g. /path/to/source) directory as reference for the touch command. Just cd to your target directory and do

find -type f -exec touch -r /path/to/source/{} {} \;

You cannot copy sub-second timestamps with rsync (yet).

This also works for directories and pseudo files (just remove or change the -type f)

4
  • This was useful for me as I needed atime to be copied. I noticed it does not copy ctime, which was ok in my case. Mar 24, 2018 at 7:44
  • Just read the manpage of 'touch'. You can set atime and mtime both with this command.
    – knorke
    Mar 27, 2018 at 12:25
  • Yes, I know you can use touch -ar but that still does not change the ctime. I suppose that's rarely desired. Mar 27, 2018 at 17:02
  • Ah, I see the problem now. Thanks. Yes, ctime is hard to change and I don't know why.
    – knorke
    Mar 28, 2018 at 8:10
3

I think rsync is the right tool to make this but if you want some script to do this than someting this can give a good start.

You can get a file list with timestamps (acces times) like this:

find . -printf '"%p" %a\n' -type f > /tmp/times

And get the appropriate time update commands from it:

 while read line; do echo touch -a -d \"${line#* }\" ${line%% *}; done < /tmp/times

It isn't a complete script but a good start place!:)

2
  • Thanks. I think I will probably stick with Rsync for the moment, but I will definitely go out to the web and learn the different components of your script, as it may be useful in the future.
    – artella
    Dec 28, 2011 at 18:38
  • That seemed to be exactly my solution! I want to preserve the times while adding some meta data to my music library. However, apparently it can't handle spaces in file names ):
    – Burcardo
    Jul 15, 2016 at 11:52
1

Well, you could certainly write a script that reads the timestamp from one side and then uses touch to set it on same file on the other side.

But that would likely take you much longer than simply letting rsync try to copy all the files. Very little data will actually be transferred (only block hashes if the files are truly identical). But the full contents of every file will have to be read on each side at the least. So of you are limited by disk bandwidth or IOPS it could take a while. But still probably less time than writing and testing a script to do it.

1
  • Thanks, I was unaware of this feature of rsync (it is discussed in wikipedia too).
    – artella
    Dec 28, 2011 at 18:36
0

For people like me who intend to modify the files and want to retain the original timestamp (e.g. you update the meta tags of your music library).

It's based on the solution provided by Stone. However, here about the modification time and a working script to restore the timestamps. FIRST do step one, then start working with your files.

  1. Preserve old timestamps. It operates from the current directory, excludes all hidden files, and saves it to the temporary file in /tmp/files. You can always change parameters, but better stay with -printf '"%t" "%p"\n' since the later touch command utilizes that.

    find . ! -iname ".*" -printf '"%t" "%p"\n' -type f > /tmp/files

  2. Modify your files as much as you like

  3. now create a file that helps you restoring the timestamps:

    while read line; do echo touch -a -d $line >> job.sh; done < /tmp/times

  4. And finally apply the old dates to the modified files

    sh job.sh

Caveat: works for files with name spacing, special characters, but for instance no files with a $ sign in it.

2
  • To avoid (some) problems with backslashes in your file names, use read -r line. Well, always use read with -r. Besides, you can avoid opening job.sh for each file. Just put the redirection at the end of the command: while read -r path; do echo touch -a -d $path ; done < /tmp/times > job.sh
    – hagello
    Feb 19, 2018 at 12:21
  • 2nd Caveat: This script does not transfer the timestamps the directories. (Well, the OP did not ask for it.)
    – hagello
    Feb 19, 2018 at 12:22
0

Best way to copy only timestamp on Windows :

To copy any file's last created/modified/accessed time stamp to another, you can use:

touch /c /m /a /r SourceFile DestFile

(This version of Touch is part of the Win32 Console ToolBox http://www.stevemiller.net/apps/ )

Robocopy "SOURCE_DIRECTORY" "DESTINATION_DIRECTORY" /E /COPYALL /DCOPY:DAT /XF . /R:10 /W:5 /V /ETA

-1

The rsync manual: man rsync lists a -t and -N switch, they might be worth fiddling with.

2
  • I couldn't see-N. Why do you recommend these anyway?
    – Tom Hale
    Oct 5, 2019 at 15:05
  • @TomHale -N (--crtimes) indeed exists, but only in newer versions of rsync. But yeah, it's almost useless for this scenario - it means "preserve create times (newness)" - as far as I know, "file create time" is never implemented by most Unix file systems, ext4 was the only major file system that included it in the specification, but still, is never actually implemented in the Linux kernel. Dec 23, 2020 at 15:34

You must log in to answer this question.

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