跨多个目录同步文件修改时间

时间:2020-03-06 14:40:05  来源:igfitidea点击:

我有一台具有两个目录树的计算机A。第一个目录包含跨越数年的原始修改日期。第二个目录是第一个目录的副本,其中包含一些其他文件。第二台计算机包含一个目录树,该目录树与计算机A上的第二个目录相同(新的mod时间和其他文件)。如何更新两台计算机上两个较新目录中的文件,以使文件的修改时间与原始文件的修改时间相同?请注意,这些目录树的大小约为10 GB,因此该解决方案必须包含一些仅将日期信息发送到第二台计算机的方法。

解决方案

我认为rsync(具有正确的选项)
将声称只发送此邮件
文件差异,大概会
算出没有差异
被转移。

--times保留我们想要的修改时间。

参见(例如)
http://linux.die.net/man/1/rsync

同时添加-I,-ignore-times不会跳过与大小和时间匹配的文件

以便所有文件都"传输"并信任rsync的文件差异优化,使其"相当有效",请参见以下手册页的摘录。

-t, --times
  This tells rsync to transfer modification times along with the files and update them on the remote system. Note that if this option is not used, the optimization that excludes files that have not been modified cannot be effective; in other words, a missing -t or -a will cause the next transfer to behave as if it used -I, causing all files to be updated (though the rsync algorithm will make the update fairly efficient if the files haven't actually changed, you're much better off using -t).

我将遍历源目录树中的所有文件,并将它们的修改时间收集到一个可以在其他目录树中运行的脚本中。我们将需要注意一些"陷阱"。首先,请确保输出脚本具有相对路径,并确保从正确的目标目录(应为目标树的根目录)中运行它。另外,更换机器时,请确保使用与生成脚本的机器相同的时区。

这是我整理的Perl脚本,将输出更新其他目录树上的时间所需的touch命令。根据目标计算机的不同,我们可能需要调整日期格式或者命令选项,但这应该为我们提供了一个起点。

#!/usr/bin/perl

my $STARTDIR="$HOME/test";

chdir $STARTDIR;
my @files = `find . -type f`;
chomp @files;

foreach my $file (@files) {
   my $mtime = localtime((stat($file))[9]);
   print qq(touch -m -d "$mtime" "$file"\n);
}

我们可以尝试的另一种方法是使用NFS添加远程目录,然后使用findtouch -r复制时间。

以下命令将确保TEST2获得与TEST1分配的日期相同的日期

touch -t `stat -t '%Y%m%d%H%M.%S' -f '%Sa' TEST1` TEST2

现在,我们可以使用"查找"实用程序查找文件,而不是在此处使用硬编码的值,然后在远程计算机上通过SSH运行touch。但是,这意味着我们可能必须为每个文件输入密码,除非我们将SSH切换为证书身份验证。我宁愿不要花一口气就做所有这一切。相反,让我们使用临时文件。首先转到有问题的目录并运行查找(我们可以按文件类型,大小,扩展名或者其他要求进行过滤,有关详细信息,请参见" man查找"。我仅按此处的文件类型进行过滤以排除任何目录):

find . -type f -print -exec stat -t '%Y%m%d%H%M.%S' -f '%Sm' "{}" \; > /tmp/original_dates.txt

现在我们有了一个看起来像这样的文件(在我的示例中,那里只有两个条目):

# cat /tmp/original_dates.txt 
./test1
200809241840.55
./test2
200809241849.56

现在,只需将文件复制到另一台计算机上,并将其放置在目录中(这样,相对文件路径就会匹配)并应用日期:

cat original_dates.txt | (while read FILE && read DATE; do touch -t $DATE "$FILE"; done)

也可以使用包含空格的文件名。

一个注意事项:我使用了stat的最后一个"修改"日期,因为这就是我们在问题中所写的内容。但是,听起来好像要使用"创建"日期(每个文件都有创建日期,上次修改日期和上次访问日期),我们需要稍微更改stat调用。

'%Sm' - last modification date
'%Sc' - creation date
'%Sa' - last access date

但是,触摸只能更改修改时间和访问时间,我认为它不能更改文件的创建时间...因此,如果这是真实意图,则我的解决方案可能不是最佳选择...但是如果问题也是;-)