rsync список каталогов с абсолютным путем в текстовом файле

9

У меня есть текстовый файл, содержащий список каталогов с его абсолютным путем

$ cat DirectoriesToCopy.txt

/data/Dir1
/data/Dir2

Я хочу использовать rsync для копирования всех этих каталогов, сохраняя его абсолютный путь в другое место.

Я попробовал следующую команду rsync, но она не работает

rsync -avr --include-from=DirectoriesToCopy.txt --exclude='*/' --exclude='/*'  /  /media/MyDestination/

Что здесь не так?

indiajoe
источник
Вы хотите передать /data/Dir1и /data/Dir2включить их содержимое в /media/MyDestination/Dir1и /media/MyDestination/Dir2? Или вы хотите включить /dataчасть? Насколько велик этот список, он слишком велик, чтобы просто перечислять эти записи в командной строке? Во всяком случае, ваши --excludeзаявления не позволяют рекурсии.
wurtel
Я хочу также перенести все файлы в эти каталоги. В этом каталоге много файлов, поэтому я бы хотел избежать создания еще одного текстового файла со всеми именами файлов.
indiajoe
Я хотел бы сохранить свой полный путь, как /media/MyDestination/data/Dir2/. Я добавил --exclude, чтобы предотвратить копирование других каталогов и файлов в /.
indiajoe
В тех случаях, когда список каталогов не очень большой, я думаю, что следующий вариант прощеrsync -av $(cat DirectotiesToCopy.txt) /media/MyDestination/
indiajoe

Ответы:

6

Используйте следующую команду:

rsync -av --include-from=DirectoriesToCopy.txt --include /data/ --exclude='/data/*' --exclude='/*/' / /media/MyDestination/

Вам нужно явно указать / data /, вы могли бы также добавить это в список в файле. Затем исключите все остальные каталоги (порядок важен для включений / исключений).

Обратите внимание, что ваше использование -rбыло излишним, поскольку оно включено в -a.

РЕДАКТИРОВАТЬ: Вы также можете достичь того же результата с:

rsync -av --relative /data/Dir1 /data/Dir2 /media/MyDestination/

Это не rsync, который заставляет вас делать сложные вещи, просто скопировать пару каталогов, он просто дает вам несколько способов сделать то же самое; в некоторых случаях путь включения / исключения может быть более подходящим, в данном случае я бы выполнил --relative вещь выше (без --relativeтого, чтобы вы в конечном итоге /media/MyDestination/Dir1и /media/MyDestination/Dir2с, --relativeвесь путь источника копируется к месту назначения).

wurtel
источник
Спасибо, что сработало. Я немного удивлен, что нужно определить такую ​​осторожную последовательность фильтров для простого копирования списка каталогов с помощью rsync. Например, если мой список каталогов не был в одном общем каталоге / data /, а вместо этого был разбросан по многим местоположениям, фильтры для определения становятся довольно сложными.
indiajoe
Смотрите мое редактирование моего ответа.
wurtel
Спасибо. Поэтому, если мой список каталогов не очень большой, я мог бы использовать флаг --relative, как показано ниже. rsync -av --relative $(cat DirectotiesToCopy.txt) /media/MyDestination/
indiajoe
Да; имейте в виду, --relativeэто просто еще один вариант.
wurtel
7

Я хочу использовать rsync для копирования всех этих каталогов [из списка], сохраняя его абсолютный путь в другое место

Не используйте --includeили --filterвариации, так как это только запутает вещи. Вместо этого используйте --files-from=_filename_. (Если вы делаете, убедитесь, что вы делаете много испытаний.)

  1. Создайте список каталогов в файле, один каталог / файл на строку.

  2. Используйте rsync --files-from=с указанным выше файлом.

  3. Используйте параметр --relative/, -Rчтобы убедиться, что исходные пути скопированы в конец места назначения.

  4. Даже если у вас есть -aвозможность, также включите -r. Со страницы руководства:

    В обоих случаях, если включена опция -r, вся иерархия dir также будет перенесена (имейте в виду, что -r необходимо явно указать с помощью --files-from, так как она не подразумевается в -a).

Завершить команду:

rsync ${DEBUG:+-nv} -arR --files-from=<list_of_files.txt> <top-level-dir>  <target-dir>

(файлы в list_of_files.txt должны быть относительными или находиться в директории верхнего уровня )

(если установлен DEBUG, rsync просто распечатывает то, что могло быть скопировано.)

Otheus
источник
1
Это то, что мне было нужно! Однако "--include-from" должно быть "--files-from". Также я использовал «--list-only», чтобы увидеть предварительный просмотр того, что будет делать RSYNC, прежде чем позволить ему работать.
Adambean
1
Спасибо, я обновил ответ. --include-fromтакже будет работать, но то, о чем я говорил, -rв значительной степени не имеет значения.
Отей
2

Руководство rsync предупреждает об этом сценарии (раздел «Включить / исключить правила шаблона»):

это не сработает:

+ /some/path/this-file-will-not-be-found
+ /file-is-included
- *

Это терпит неудачу, потому что родительский каталог "some"исключен '*'правилом, поэтому rsync никогда не посещает какие-либо файлы в каталогах "some"или "some/path". Одно из решений состоит в том, чтобы запросить включение всех каталогов в иерархии, используя одно правило: "+ */"(поместите его где-нибудь перед "- *"правилом) и, возможно, используйте --prune-empty-dirsопцию. Другое решение заключается в добавлении определенных правил включения для всех родительских каталогов, которые необходимо посетить. Например, этот набор правил работает нормально:

+ /some/
+ /some/path/
+ /some/path/this-file-is-found
+ /file-also-included
- *

В вашем случае, я думаю , самый простой подход был бы препроцессировать список каталогов , которые включают в себя так , что всякий раз , когда вы включаете /path/to/foo, вы также включают в себя все родительские каталоги ( /path/to, /path, /), а также включать подкаталоги исходных каталогов ( /path/to/foo/***), и после того, как на все это есть правило, исключающее все, что ранее не перечислялось ( *).

<DirectoriesToCopy.txt awk '
    {print "+ " $0 "/***"; while (sub(/\/+[^\/]+\/*$/, "/")) print "+ " $0}
    END {print "- *"}
' >rsync-rules.txt
rsync -avr --include-from=rsync-rules.txt  /  /media/MyDestination/
Жиль "ТАК - перестань быть злым"
источник
Спасибо за подробное объяснение и скрипт для создания файла правил. Теперь я понимаю проблему. Я все еще чувствую, что для rsync было бы хорошо иметь опцию, например --dirs-from = DirectoriesToCopy.txt, в качестве краткого описания всех сложных фильтров.
indiajoe