我有一台带有两个目录树的计算机A.第一个目录包含跨越几年的原始mod日期。第二个目录是第一个目录的副本,其中包含一些其他文件。第二台计算机包含一个目录树,它与计算机A上的第二个目录相同(新的mod时间和其他文件)。如何更新两台机器上两个较新目录中的文件,以便文件的mod时间与原始文件相同?请注意,这些目录树的大小为10千兆字节,因此解决方案必须包含一些仅将日期信息发送到第二台计算机的方法。
答案 0 :(得分:2)
以下命令将确保TEST2获得与TEST1具有相同的日期
touch -t `stat -t '%Y%m%d%H%M.%S' -f '%Sa' TEST1` TEST2
现在,您可以使用“find”实用程序找到文件,然后在远程计算机上通过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
然而,触摸只能改变修改时间和访问时间,我认为它不能改变文件的创建时间......所以如果这是你的真实意图,我的解决方案可能是次优的......但在这种情况下你的问题也是如此; - )
答案 1 :(得分:2)
Paul的答案部分正确,rsync
能够做到这一点,但是参数不同。正确的命令是
rsync -Prt --size-only original_dir copy_dir
其中-P
启用部分转移并显示进度指示器,-r
通过子目录进行递归,-t
保留时间戳,--size-only
不传输大小匹配的文件
答案 2 :(得分: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);
}
答案 3 :(得分:1)
您可以尝试的另一种方法是使用NFS附加远程目录,然后使用find
和touch -r
复制时间。
答案 4 :(得分:0)
我认为rsync(使用正确的选项) 会这样做 - 它声称只发送 文件差异,所以可能会 确定没有差异 转移。
- 次保留修改时间,这就是你想要的。
参见(例如) http://linux.die.net/man/1/rsync
另外添加-I, - ignore-times不会跳过与大小和时间匹配的文件
这样所有文件都被“转移”并信任rsync的文件差异优化,使其“相当高效” - 请参阅下面手册页的摘录。
-t, - 次 这告诉rsync将修改时间与文件一起传输并在远程系统上更新它们。请注意,如果未使用此选项,则排除尚未修改的文件的优化无效;换句话说,缺少-t或-a将导致下一次传输的行为就像它使用-I一样,导致所有文件都被更新(尽管如果文件实际上没有更改,rsync算法将使更新相当有效,你最好不要使用-t)。
答案 5 :(得分:0)
我使用了以下Python脚本。
Python脚本的运行速度比为每个文件创建新流程的方法要快得多(比如使用find
和stat
)。下面的解决方案也适用于系统之间的时区差异,因为它使用UTC时间。它也适用于包含空格的路径(但不包含包含换行符的路径!)。它没有为符号链接设置时间,因为the operating system provides no mechanism to modify the timestamp of a symlink,但在文件管理器中,无论如何都会显示符号链接所指向的文件的时间。它使用maxTime
参数来避免重置从原始目录复制后实际修改的文件的日期。
<强> listMTimes.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)
<强> setMTimes.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