I recently transferred a few thousand files, totalling gigabytes, from one computer to another over a slowish internet connection. At the end of the transfer, I realized the process I used had lost all the original file timestamps. Rather, all the files on the destination machine had a create/modify date of when the transfer occurred. In this particular case I had uploaded files to Amazon S3 from end then downloaded them from another, but there are numerous other ways to transfer files that lose the timestamps; for example, many FTP clients do so by default.
This file transfer took many hours, so I wasn’t inclined to delete and try again with a better (timestamp-preserving) transfer process. Rather, it shouldn’t be very hard to fix them in-place.
Both machines were Windows servers; neither had a broad set of Unix tools installed. If I had those present, the most obvious solution would be a simple rsync command, which would fix the timestamps without retransferring the data. But without those tools present, and with an unrelated desire to keep these machines as “clean” as possible, plus a firewall obstacle to SSH, I looked elsewhere for a fix.
I did, however, happen to have a partial set of Unix tools (in the form of the MSYS tools that come with MSYSGIT) on the source machine. After a few minutes of puzzling, I came up with this approach:
- Run a command on the source machine
- … which looks up the timestamp of each file
- … and stores those in the form of batch file
- Then copy this batch file to the destination machine and run it.
Here is the source machine command, executed at the top of the file tree to be fixed:
find . -print0 | xargs -0 stat -t "%d-%m-%Y %T" -f 'nircmd.exe setfilefoldertime "%N" "%Sc" "%Sm"' | tr '/' '\\' >~/fix_dates.bat
I broken it up to several lines here, but it’s intended as one long command.
- “find” gets the names of every file and directory in the file tree
- xargs feeds these to the stat command
- stat gets the create and modify dates of each file/directory, and formats the results in a very configurable way
- tr converts the Unix-style “/” paths to Windows-style “\” paths.
- The results are redirected to (stored in) a batch file.
As far as I can tell, the traditional set of Windows built in command line tools does not include a way to set a file or directory’s timestamps. I haven’t spent much time with Powershell yet, so I used the (very helpful) NIRCMD command line utilities, specifically the setfilefoldertime subcommand. The batch file generated by the above process is simply a very long list of lines like this:
nircmd.exe setfilefoldertime "path\filename" "19-01-2000 04:50:26" "19-01-2000 04:50:26"
I copied this batch file to the destination machine and executed it; it corrected the timestamps, the problem was solved.
powershell will definitely do it, it’s worth it
If anyone wants to show how to do this same thing with PowerShell, I’ll happily include it here or link to it.
An extremely helpful reader wrote in with this – text lightly edited by my (Kyle):
Unfortunately, I was not able to get your command to work in Ubuntu Linux 12.04. The “stat” command in that environment does not accept a date-formatting option as shown in your command.
I was able to come up with the following long-winded command to get the job done; although it is long and inefficient, it works:
find . -exec echo -n nircmd.exe setfilefoldertime \"{}\" "\"\" " \; -exec sh -c 'stat -c "%Y" "{}" | awk "{print strftime(\"\\\"%d-%m-%Y %T\\\"\", \$1)}"' \; | tr '/' '\\' > nirdatefix.cmd
It uses a standard echo to give the first piece of the nircmd command. Then, it performs the stat command, piping it through awk to convert to the proper date format. It uses tr the same way you specified.
My use case: I use ownCloud as a privately-hosted alternative to Dropbox. I put my music on it, too. My work computer became out of sync with my music, and 3GB was going to take a long time to transfer from my server at home. This music had already been synchronized to my Android phone using FolderSync, so I copied the music from my phone to save some time. However, the ownCloud Windows client still kept trying to resynchronize all of it from the server, anyway.
It turned out that the files from my phone were 1 second behind on their timestamps! A FolderSync bug? Who knows. Using my modified version of your command, I went into the relevant ownCloud folder on the server and ran it.