2008-09-24 56 views
2

我有一台带有两个目录树的计算机A.第一个目录包含跨越几年的原始模型日期。第二个目录是第一个目录的副本和几个附加文件。还有第二台计算机包含一个与计算机A上的第二个目录相同的目录树(新的mod时间和附加文件)。如何更新两台机器上两个较新目录中的文件,以便文件的修改时间与原始文件相同?请注意,这些目录树大小为10 GB,所以解决方案必须包含一些仅向第二台计算机发送日期信息的方法。跨多个目录的同步文件修改时间

回答

0

我认为rsync的(与正确的选项) 将做到这一点 - 它声称只发送 文件差异,所以想必 工作了,有没有差异 转移。

- 次保留修改时间,这是你想要的。

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

同时添加-I,--ignore次不跳过匹配的大小和时间

使所有文件“转移”和信任的文件rsync的的文件不同的优化,以使其“相当有效。” - 节选看到从下面的man page

-t,--times 这告诉rsync的传输与文件一起修改时间和更新它们的遥控器上SYST EM。请注意,如果未使用此选项,排除未被修改的文件的优化将无法生效;换句话说,缺少-t或-a将导致下一次传输的行为就像使用-I一样,导致所有文件都被更新(尽管如果文件没有真正改变,rsync算法会使更新效率更高,你使用-t)会好得多。

+0

其实rsync使用日期/时间来决定是否有差异(它只会同步文件具有较新的mod本地的日期比远程);你不能使用rsync来做这件事。此外rsync不会同步任何东西,除非它决定同步文件内容,并且这被排除在提问者之外。 – Mecki 2008-09-24 17:08:14

1

我会浏览源目录树中的所有文件,并将修改时间从它们收集到可以在其他目录树上运行的脚本中。你需要小心几个'陷阱'。首先,确保您的输出脚本具有相对路径,并确保您从适当的目标目录(它应该是目标树的根目录)运行它。另外,在更换机器时,请确保您使用的是与生成脚本的计算机上相同的时区。

下面是我放在一起的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); 
} 
1

另一种方法,你可以尝试是使用NFS来连接远程目录,然后使用findtouch -r复制倍。

2

以下命令将确保TEST2获得分配了TEST1具有

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

现在不是这里使用硬编码值相同的日期,你可以使用“查找”工具,然后运行查找文件通过远程计算机上的SSH进行触摸。但是,这意味着您可能必须输入每个文件的密码,除非您将SSH切换为证书验证。我宁愿不要在一个超级花式的单线上做这一切。相反,让我们使用临时文件。首先进入有问题的目录并运行一个查找(你可以根据文件类型,大小,扩展名进行过滤,无论你喜欢什么,请参阅“man find”以获取详细信息。我只是通过类型文件进行过滤以排除任何目录):

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中的最后一个“修改”日期,因为这是您在问题中写的内容。然而,听起来好像你想使用“创建”日期(每个文件都有一个创建日期,最后修改日期和最后访问日期),你需要稍微改变统计调用。

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

然而,触摸只能更改修改时间和访问时间,我觉得它不能改变文件的创建时间......因此,如果这是你的真实意图,我的解决方案可能是分最佳...但在这种情况下,您的问题也是如此;-)

+0

我最后不得不使用touch new_file -t \`date -d @ \``stat -t -c“%Y”old_file \\`+%Y%m%d%H%M%S \` – kormoc 2012-06-06 21:23:02

2

Paul的答案部分正确,rsync是能够做到这一点,但具有不同的参数。正确的命令是

rsync -Prt --size-only original_dir copy_dir 

其中-P使局部传输和显示进度指示,-r递归通过子目录,-t保留时间标记和--size-only不转移匹配大小的文件。

0

我改用下面的Python脚本。

Python脚本的运行速度比为每个文件创建新进程的方法快得多(如使用findstat)。下面的解决方案也适用于系统之间的时区差异,因为它使用UTC时间。它也适用于包含空格的路径(但不包含包含换行符的路径!)。它不会为符号链接设置时间,因为the operating system provides no mechanism to modify the timestamp of a symlink,但是在文件管理器中,符号链接指向的文件时间反而显示。它使用maxTime参数来避免重置从原始目录复制后实际修改的文件的日期。

listMTim​​es.py:

import os 
from datetime import datetime 
from pytz import utc 

for dirpath, dirnames, filenames in os.walk('./'): 
    for name in filenames+dirnames: 
     path = os.path.join(dirpath, name) 
     # Avoid symlinks because os.path.getmtime and os.utime get and 
     # set the time of the pointed file, and in the new directory, 
     # the link may have been redirected. 
     if not os.path.islink(path): 
      mtime = datetime.fromtimestamp(os.path.getmtime(path), utc) 
      print(mtime.isoformat()+" "+path) 

setMTim​​es。PY:

import datetime, fileinput, os, sys, time 
import dateutil.parser 
from pytz import utc 

# Based on 
# http://stackoverflow.com/questions/6999726/python-getting-millis-since-epoch-from-datetime 
def unix_time(dt): 
    epoch = datetime.datetime.fromtimestamp(0, utc) 
    delta = dt - epoch 
    return delta.total_seconds() 

if len(sys.argv) != 2: 
    print('Syntax: '+sys.argv[0]+' <maxTime>') 
    print(' where <maxTime> an ISO time, e. g. "2013-12-02T23:00+02:00".') 
    exit(1) 

# A file with modification time newer than maxTime is not reset to 
# its original modification time. 
maxTime = unix_time(dateutil.parser.parse(sys.argv[1])) 

for line in fileinput.input([]): 
    (datetimeString, path) = line.rstrip('\r\n').split(' ', 1) 
    mtime = dateutil.parser.parse(datetimeString) 
    if os.path.exists(path) and not os.path.islink(path): 
     if os.path.getmtime(path) <= maxTime: 
      os.utime(path, (time.time(), unix_time(mtime))) 

用法:在第一目录(原)运行

python listMTimes.py >/tmp/original_dates.txt 

然后在第二目录(原始的一个副本,可能会进行一些修改过的文件/加入/删除)运行这样的事情:

python setMTimes.py 2013-12-02T23:00+02:00 </tmp/original_dates.txt 
相关问题