代码之家  ›  专栏  ›  技术社区  ›  Mark Roddy

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

  •  3
  • Mark Roddy  · 技术社区  · 16 年前

    6 回复  |  直到 16 年前
        1
  •  2
  •   Mecki    16 年前

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

    现在,您可以使用“find”实用程序查找文件,然后通过SSH在远程机器上运行touch,而不是在这里使用硬编码值。但是,这意味着您可能必须为每个文件输入密码,除非您将SSH切换到cert身份验证。我可不想把这一切都写在一个超级花哨的单行诗里。我们来处理临时文件。首先转到有问题的目录并运行一个find(您可以根据文件类型、大小、扩展名、任何您喜欢的方式进行筛选,有关详细信息,请参阅“manfind”。我只是在这里按类型文件筛选以排除任何目录):

    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
    

    但是,touch只能改变修改时间和访问时间,我认为它不能改变文件的创建时间。。。所以如果这是你的真正意图,我的解决方案可能是次优。。。但在这种情况下,你的问题也是;-)

        2
  •  2
  •   marton78    12 年前

    保罗的回答部分是正确的, rsync

    rsync -Prt --size-only original_dir copy_dir
    

    哪里 -P 启用部分传输并显示进度指示器, -r -t 保存时间戳和 --size-only 不传输大小匹配的文件。

        3
  •  1
  •   Jeremy Bourque    16 年前

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

    下面是我编写的一个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);
    }
    
        4
  •  1
  •   Jeremy Bourque    16 年前

    您可以尝试的另一种方法是使用NFS附加远程目录,然后使用 find touch -r .

        5
  •  0
  •   The Archetypal Paul    16 年前

    会这样做-它声称只发送 弄清楚没有区别

    --times保留修改时间,这是您想要的。

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

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

    因此,所有文件都被“传输”并信任rsync的文件差异优化,使其“相当高效”——请参阅下面手册页的摘录。

    这告诉rsync将修改时间与文件一起传输,并在远程系统上更新它们。请注意,如果不使用此选项,则排除未修改文件的优化将无法生效;换句话说,缺少-t或-a将导致下一次传输的行为与使用-I相同,导致所有文件都被更新(虽然rsync算法将使更新相当有效,如果文件实际上没有更改,那么使用-t会更好)。

        6
  •  0
  •   Jaan    11 年前

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

    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)
    

    设置时间.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