rsync: Синхронизирующие папки, но сохраняют дополнительные файлы в цели

Я начинаю с rsync и попробованный для использования его для хранения двух папок в локальной системе синхронизировавшими. У меня есть исходная папка, содержание которой изменяется со временем (некоторые файлы добавляются, некоторые изменения и некоторые удаленные), и целевая папка, что я хочу почти быть зеркалом источника. Таким образом, то, что я попробовал, использовало rsync как это:

rsync -a --delete "${source_dir}" "${target_dir}";

Это действительно сохраняет содержание цели тем же самым как содержание источника. Однако я хотел бы смочь добавить некоторые файлы для предназначения а не к источнику, но я не хочу, чтобы они были удалены каждый раз, я делаю rsync. С другой стороны, файлы, которые раньше синхронизировались и затем были удалены в источнике, должны все еще быть удалены.

Существует ли способ сделать это, не имея необходимость изменять команду для каждого файла, который я хочу исключенный?

Обновление: Я должен упомянуть, что не ограничен rsync. Если другая программа сделала задание, это прекрасно также. Я просто попытался решить это использование rsync.

10
задан 1 February 2017 в 14:42

2 ответа

rsync назвали опцию --exclude-from опция, которая позволяет Вам создавать файл, содержащий список любых файлов, которые требуется исключить. Можно обновить этот файл каждый раз, когда Вы хотите добавить новое исключение или удалить старое.

Если Вы создаете исключить файл в /home/user/rsync_exclude новая команда была бы:

rsync -a --delete --exclude-from="/home/user/rsync_exclude" "${source_dir}" "${target_dir}"

При создании исключить файла списка необходимо поместить каждое правило исключения об отдельной строке. Исключения относительно Вашего исходного каталога. Если Ваш /home/user/rsync_exclude файл содержал следующие опции:

secret_file
first_dir/subdir/*
second_dir/common_name.*
  • Любой файл или каталог называют secret_file в Вашем источнике будет исключен каталог.
  • Любые файлы в ${source_dir}/first_dir/subdir будет исключен, но пустая версия subdir будет синхронизироваться.
  • Любые файлы в ${source_dir}/second_dir с префиксом common_name. будет проигнорирован. Так common_name.txt, common_name.jpg и т.д.
9
ответ дан 23 November 2019 в 04:27

Так как Вы упомянули: Я не ограничен rsync:

Сценарий для поддержания зеркала, позволяя добавлять дополнительные файлы для предназначения

Ниже сценария, который делает точно, что Вы описываете.

Скрипт может быть запущен в подробном режиме (чтобы быть установленным в сценарии), который произведет прогресс резервного (зеркальное отражение). Никакая потребность сказать это не может также использоваться для входа резервных копий:

Подробная опция

enter image description here


Понятие

1. На первом резервном копировании, сценарии:

  • создает файл (в целевом каталоге), где все файлы и каталоги перечислены; .recentfiles
  • создает точную копию (зеркало) всех файлов и каталогов в целевом каталоге

2. На следующем и так далее копируют

  • Сценарий сравнивает структуру каталогов и дату (даты) модификации файлов. Новые файлы и директора в источнике копируются в зеркало. В то же время второй (временный) файл создается, перечисляя текущие файлы и директоров в исходном каталоге; .currentfiles.
  • Впоследствии, .recentfiles (список ситуации на предыдущем резервном копировании), сравнивается .currentfiles. Только файлы от .recentfiles которые не находятся в .currentfiles очевидно, удалены из источника и будет удален из цели.
  • Регистрирует Вы вручную добавили к целевой папке, не находятся в так или иначе "замеченном" сценарием и оставлены в покое.
  • Наконец, временный файл .currentfiles переименован к .recentfiles служить следующему резервному циклу и так далее.

Сценарий

#!/usr/bin/env python3
import os
import sys
import shutil

dr1 = sys.argv[1]; dr2 = sys.argv[2]

# --- choose verbose (or not)
verbose = True
# ---

recentfiles = os.path.join(dr2, ".recentfiles")
currentfiles = os.path.join(dr2, ".currentfiles")

if verbose:
    print("Counting items in source...")
    file_count = sum([len(files)+len(d) for r, d, files in os.walk(dr1)])
    print(file_count, "items in source")
    print("Reading directory & file structure...")
    done = 0; chunk = int(file_count/5); full = chunk*5

def show_percentage(done):
    if done % chunk == 0:
        print(str(int(done/full*100))+"%...", end = " ")

for root, dirs, files in os.walk(dr1):
    for dr in dirs:
        if verbose:
            if done == 0:
                print("Updating mirror...")
            done = done + 1
            show_percentage(done) 
        target = os.path.join(root, dr).replace(dr1, dr2)
        source = os.path.join(root, dr)
        open(currentfiles, "a+").write(target+"\n")
        if not os.path.exists(target):
            shutil.copytree(source, target)
    for f in files:
        if verbose:
            done = done + 1
            show_percentage(done)
        target = os.path.join(root, f).replace(dr1, dr2)
        source = os.path.join(root, f)
        open(currentfiles, "a+").write(target+"\n") 
        sourcedit = os.path.getmtime(source)
        try:
            if os.path.getmtime(source) > os.path.getmtime(target):
                shutil.copy(source, target)   
        except FileNotFoundError:
            shutil.copy(source, target)

if verbose:
    print("\nChecking for deleted files in source...")

if os.path.exists(recentfiles):
    recent = [f.strip() for f in open(recentfiles).readlines()]
    current = [f.strip() for f in open(currentfiles).readlines()]
    remove = set([f for f in recent if not f in current])
    for f in remove:
        try:
            os.remove(f)
        except IsADirectoryError:
            shutil.rmtree(f)
        except FileNotFoundError:     
            pass
        if verbose:
            print("Removed:", f.split("/")[-1])

if verbose:
    print("Done.")

shutil.move(currentfiles, recentfiles)

Как использовать

  1. Скопируйте сценарий в пустой файл, сохраните его как backup_special.py
  2. Изменение - если Вы хотите - подробная опция в заголовке сценария:

    # --- choose verbose (or not)
    verbose = True
    # ---
    
  3. Выполните его с источником и целью как аргументы:

     python3 /path/to/backup_special.py <source_directory> <target_directory>
    

Скорость

Я протестировал сценарий на каталоге на 10 ГБ приблизительно с 40 000 файлов и директоров на моем сетевом диске (NAS), он сделал резервное копирование в в значительной степени то же время как rsync.

Обновление целого каталога заняло только несколько секунд больше, чем rsync на 40 000 файлов, который является imo приемлемый и не удивительно, так как сценарий должен сравнить содержание с последним сделанным резервным копированием.

6
ответ дан 23 November 2019 в 04:27

Другие вопросы по тегам:

Похожие вопросы: