Как использовать Rsync для копирования только определенных подкаталогов (одинаковые имена в нескольких каталогах)

У меня такая структура каталогов на сервере 1:

  • данные
    • Company1
      • unique_folder1
      • other_folder
      • ...
    • Общества2
      • unique_folder1
      • ...
    • ...

И я хочу дублировать эту структуру папок на сервере 2, но копировать только каталоги/подкаталоги unique_folder1. То есть в результате должен быть:

  • данные
    • Company1
      • unique_folder1
    • Общества2
      • unique_folder1
    • ...

Я знаю, что rsync очень хорош для этого. Я пробовал опции include/exclude без успеха.

например. Я пробовал:

rsync -avzn --list-only --include '*/unique_folder1/**' --exclude '*' -e ssh [email protected]:/path/to/old/data/ /path/to/new/data/

Но, в результате, я не вижу никаких файлов/каталогов:

receiving file list ... done
sent 43 bytes  received 21 bytes  42.67 bytes/sec
total size is 0  speedup is 0.00 (DRY RUN)

Что случилось? Идеи?


Дополнительная информация: У меня есть sudo доступ к обоим серверам. Одна из моих идей - использовать команду find и cpio вместе, чтобы скопировать в новый каталог с нужным контентом и после этого использовать rsync. Но это очень медленно, есть много файлов и т.д.

Ответ 1

Я нашел причину. Что касается меня - не ясно, что Rsync работает таким образом.
Поэтому правильная команда (только для каталога company1) должна быть:

rsync -avzn --list-only --include 'company1/' --include 'company1/unique_folder1/***' --exclude '*' -e ssh [email protected]:/path/to/old/data/ /path/to/new/data

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


Конечные вещи, которые нам нужно сделать:

1. Создайте файл include на сервере 1, поэтому его содержимое будет (я использовал ls и awk):

+ company1/  
+ company1/unique_folder1/***  
...  
+ companyN/  
+ companyN/unique_folder1/***  

2.Copy include.txt на сервер 2 и используйте такую ​​команду:

rsync -avzn                                        \
      --list-only                                  \
      --include-from '/path/to/new/include.txt'    \
      --exclude '*'                                \
      -e ssh [email protected]:/path/to/old/data/    \
      /path/to/new/data

Ответ 2

Если первый шаблон соответствия исключает каталог, то все его потомки никогда не пройдут. Если вы хотите включить глубокий каталог, например. company*/unique_folder1/**, но исключить все остальное *, вам необходимо указать rsync, чтобы включить всех своих предков:

rsync -r -v --dry-run                       \
    --include='/'                           \
    --include='/company*/'                  \
    --include='/company*/unique_folder1/'   \
    --include='/company*/unique_folder1/**' \
    --exclude='*'

Вы можете использовать расширение bash s для сохранения некоторого набора текста. После расширения фигурной скобки следующая команда точно такая же, как предыдущая:

rsync -r -v --dry-run --include=/{,'company*/'{,unique_folder1/{,'**'}}} --exclude='*'

Ответ 3

Например, если вы хотите синхронизировать только target/classes/ и target/lib/ с удаленной системой, выполните

rsync -vaH --delete --delete-excluded --include='classes/***' --include='lib/***' \
      --exclude='*' target/ [email protected]:/deploy/path/

Важные вещи для просмотра:

  • Не забывайте " / " в конце патчей, иначе вы получите копию в подкаталог.
  • Порядок --include, --exclude.
  • В отличие от других ответов, начиная с " / ", параметр include/exclude не нужен, они будут автоматически добавлены в исходный каталог (target/ в примере).
  • Чтобы проверить, что именно произойдет, мы можем использовать флаги --dry-run, как говорят другие ответы.
  • --delete-excluded удалит весь контент в целевом каталоге, кроме подкаталогов, которые мы специально включили. Это следует использовать с умом! По этой причине --delete, он не удаляет исключенные файлы на удаленной стороне по умолчанию (все остальные, да), его следует снова указывать рядом с обычным --delete.