Время модификации файла синхронизации в нескольких каталогах - PullRequest
3 голосов
/ 24 сентября 2008

У меня есть компьютер A с двумя деревьями каталогов. Первый каталог содержит оригинальные даты мода, которые охватывают несколько лет. Второй каталог является копией первого с несколькими дополнительными файлами. Есть второй компьютер be, который содержит дерево каталогов, которое совпадает со вторым каталогом на компьютере A (новые времена мода и дополнительные файлы). Как обновить файлы в двух новых каталогах на обеих машинах, чтобы время модификации файлов совпадало с временем оригинала? Обратите внимание, что эти деревья каталогов имеют порядок 10 гигабайт, поэтому решение должно включать некоторый метод отправки только информации о дате на второй компьютер.

Ответы [ 6 ]

2 голосов
/ 20 мая 2013

Ответ Павла частично верен, rsync может сделать это, но с другими параметрами. Правильная команда

rsync -Prt --size-only original_dir copy_dir

, где -P включает частичную передачу и отображает индикатор выполнения, -r рекурсивно просматривает подкаталоги, -t сохраняет метки времени и --size-only не передает файлы, которые соответствуют по размеру.

2 голосов
/ 24 сентября 2008

Следующая команда убедится, что TEST2 получает ту же дату, назначенную для TEST1

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

Теперь вместо использования жестко запрограммированных значений вы можете найти файлы с помощью утилиты "find", а затем запустить touch через SSH на удаленной машине. Однако это означает, что вам, возможно, придется вводить пароль для каждого файла, если только вы не переключите SSH для проверки подлинности. Я бы предпочел не делать все это в супер причудливой строчке. Вместо этого давайте работать с временными файлами. Сначала перейдите к рассматриваемому каталогу и запустите поиск (вы можете фильтровать по типу файла, размеру, расширению, что угодно, смотрите подробности в разделе «поиск человека». Я просто фильтрую по типу файла здесь, чтобы исключить любые каталоги):

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 голос
/ 24 сентября 2008

Другой подход, который вы можете попробовать, - присоединить удаленный каталог с помощью NFS, а затем скопировать время, используя find и touch -r.

1 голос
/ 24 сентября 2008

Я бы просмотрел все файлы в исходном дереве каталогов и собрал из них время модификации в сценарий, который я мог бы запустить в других деревьях каталогов. Вы должны быть осторожны с несколькими «хитами». Во-первых, убедитесь, что ваш выходной скрипт имеет относительные пути, и убедитесь, что вы запускаете его из правильного целевого каталога, который должен быть корневым каталогом целевого дерева. Кроме того, при смене компьютеров убедитесь, что вы используете тот же часовой пояс, что и на компьютере, на котором был создан скрипт.

Вот сценарий 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);
}
0 голосов
/ 04 декабря 2013

Вместо этого я использовал следующие скрипты Python.

Сценарии Python работают намного быстрее, чем подход, создающий новые процессы для каждого файла (например, с использованием find и stat). Приведенное ниже решение также работает в случае различий часовых поясов между системами, поскольку оно использует время UTC. Он также работает с путями, содержащими пробелы (но не путями, содержащими новую строку!). Он не устанавливает время для символьных ссылок, потому что операционная система не предоставляет механизма для изменения временной метки символической ссылки , но в файловом менеджере время файла, на который указывает символическая ссылка, отображается в любом случае. Он использует параметр 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
0 голосов
/ 24 сентября 2008

Я думаю, что Rsync (с правильными параметрами) будет делать это - он утверждает, что отправлять только файловые различия, поэтому, вероятно, будет выяснить, что нет различий быть переданным.

- времена сохраняют времена модификации, что вы и хотите.

См. (Например) http://linux.die.net/man/1/rsync

Также добавьте -I, --ignore-times, не пропускайте файлы, которые соответствуют размеру и времени

чтобы все файлы были "переданы" и доверены оптимизации различий в файлах rsync, чтобы сделать ее "довольно эффективной" - см. Выдержку из справочной страницы ниже.

-t, --times Это говорит rsync передавать время модификации вместе с файлами и обновлять их в удаленной системе. Обратите внимание, что если этот параметр не используется, оптимизация, которая исключает файлы, которые не были изменены, не может быть эффективной; другими словами, отсутствие -t или -a приведет к тому, что следующая передача будет вести себя так, как если бы она использовала -I, что приведет к обновлению всех файлов (хотя алгоритм rsync сделает обновление достаточно эффективным, если файлы фактически не изменились , вам гораздо лучше использовать -t).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...