Как выполнить синхронизацию только определенного списка файлов?

95

У меня около 50 файлов в различных подкаталогах, которые я хотел бы отправить на удаленный сервер. Я подумал, что rsync сможет сделать это за меня, используя параметр --include-from. Без опции --exclude = "*" все файлы в каталоге синхронизируются, с этой опцией файлы не синхронизируются.

rsync -avP -e ssh --include-from=deploy/rsync_include.txt --exclude=* ./ root@0.0.0.0:/var/www/ --dry-run

Сначала я запускаю его как сухой, и 0.0.0.0, очевидно, заменяется IP-адресом удаленного сервера. Содержимое rsync_include.txt - это разделенный новой строкой список относительных путей к файлам, которые я хочу загрузить.

Есть ли лучший способ сделать это, чтобы убежать от меня в понедельник утром?

Дэн Стил
источник

Ответы:

4

Изменить: ответ Иосипа Родена ниже лучше. Пожалуйста, используйте это!

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

# rsync -avP -e ssh `cat deploy/rsync_include.txt` root@0.0.0.0:/var/www/

Однако это предполагает, что ваш список не настолько длинный, что длина командной строки будет проблемой и что rsync_include.txtфайл содержит только реальные пути (т.е. без комментариев и без регулярных выражений).

Уэс Хардакер
источник
9
К сожалению, это не работает с большим списком или с файлами с пробелами в имени.
Wes Modes
3
[Список аргументов слишком длинный]
Данко Давид
По умолчанию xargs добавляет аргументы из stdin в конец командной строки. Это не работает, поскольку rsync требует, чтобы последний аргумент был местом назначения. Некоторые версии xargs могут вместо этого вставлять аргументы в середину командной строки. Это должно работать, если вы не возражаете, что он может запускать rsync более одного раза, когда список файлов длинный. В любом случае, rsync --files-fromэто, вероятно, более простое и надежное решение :)
Lassi
Уэс Хардакер: Действительно ли ваше « Правка» и ссылка на «Ответ Джосипа Родена » относится к ответу @atp, который отредактировал Роден?
Симус
234

Есть флаг, --files-fromкоторый делает именно то, что вы хотите. Откуда man rsync:

--files-from=FILE

Использование этой опции позволяет вам указать точный список файлов для передачи (как прочитанных из указанного ФАЙЛА или - для стандартного ввода). Он также настраивает поведение rsync по умолчанию, чтобы упростить перенос только указанных файлов и каталогов:

  • Подразумевается параметр --relative (-R), который сохраняет информацию о пути, указанную для каждого элемента в файле (используйте --no-relative или --no-R, если вы хотите отключить это).

  • Подразумевается параметр --dirs (-d), который будет создавать каталоги, указанные в списке, в месте назначения, а не шумно их пропускать (используйте --no-dirs или --no-d, если вы хотите отключить это).

  • Поведение параметра --archive (-a) не подразумевает --recursive (-r), поэтому укажите его явно, если хотите.

  • Эти побочные эффекты изменяют состояние rsync по умолчанию, поэтому положение параметра --files-from в командной строке не влияет на то, как анализируются другие параметры (например, -a работает одинаково до или после --files- from, как и --no-R и все другие параметры).

Имена файлов, считываемые из ФАЙЛА, относятся к исходному каталогу - все начальные косые черты удаляются, и никаким ссылкам «..» не разрешается идти выше исходного каталога. Например, возьмите эту команду:

rsync -a --files-from=/tmp/foo /usr remote:/backup

Если / tmp / foo содержит строку «bin» (или даже «/ bin»), каталог / usr / bin будет создан как / backup / bin на удаленном хосте. Если он содержит «bin /» (обратите внимание на косую черту в конце), непосредственное содержимое каталога также будет отправлено (без необходимости явного упоминания в файле - это началось в версии 2.6.4). В обоих случаях, если была включена опция -r, вся иерархия этого каталога также будет перенесена (имейте в виду, что -r необходимо явно указать с помощью --files-from, поскольку это не подразумевается -a). Также обратите внимание, что эффект параметра (включен по умолчанию) --relative заключается в дублировании только информации о пути, считанной из файла - он не вызывает дублирование пути исходной спецификации (в данном случае / usr) .

Кроме того, файл --files-from может быть прочитан с удаленного хоста, а не с локального, если вы укажете «хост:» перед файлом (хост должен соответствовать одному концу передачи). В качестве сокращения вы можете указать просто префикс ":", означающий "использовать удаленный конец передачи". Например:

rsync -a --files-from=:/path/file-list src:/ /tmp/copy

Это скопирует все файлы, указанные в файле / path / file-list, который был расположен на удаленном хосте "src".

Если указаны параметры --iconv и --protect-args и имена файлов --files-from отправляются с одного хоста на другой, имена файлов будут переведены из кодировки хоста-отправителя в кодировку хоста-получателя.

ПРИМЕЧАНИЕ: сортировка списка файлов во вводе --files-from помогает rsync быть более эффективным, так как это позволит избежать повторного посещения элементов пути, которые являются общими для соседних записей. Если входные данные не отсортированы, некоторые элементы пути (подразумеваемые каталоги) могут быть просканированы несколько раз, и rsync в конечном итоге удалит их дубликаты после того, как они будут преобразованы в элементы списка файлов.

атп
источник
23
Обратите внимание, что вам все равно необходимо указать каталог, в котором находятся перечисленные файлы, например: rsync -av --files-from=file-list . target/для копирования файлов из текущего каталога.
Николас Маттиа
7
Да, и еще раз заявить: The filenames that are read from the FILE are all relative to the source dir.
atp
Ах, пропустил, извините!
Николас Маттиа
1
если в файле из файлов есть что-то, начинающееся с ..rsync, похоже, игнорирует ..выдачу мне ошибки, например rsync: link_stat "/home/michael/test/subdir/test.txt" failed: No such file or directory(в этом случае запускается из каталога "test" и пытается указать "../subdir/test.txt", который действительно существует.
Michael
Можно --files-fromли комбинировать аргумент с явным списком включений и исключений, и будут ли файлы из списка, добавленные с помощью, --files-fromпереопределять существующие правила исключения, чтобы они включались, если они появляются в файле?
highsciguy
13

--files-from=Если вы хотите, чтобы абсолютный путь оставался неизменным, параметр нуждается в завершающей косой черте. Итак, ваша команда будет выглядеть примерно так:

rsync -av --files-from=/path/to/file / /tmp/

Это можно сделать, как если бы имеется большое количество файлов, и вы хотите скопировать все файлы по пути x. Таким образом, вы должны найти файлы и передать результат в файл, как показано ниже:

find /var/* -name *.log > file
Вакас Хан
источник
9

Для справки, ни один из приведенных выше ответов не помог, кроме одного. Подводя итог, вы можете выполнить операцию резервного копирования --files-from=, используя:

 rsync -aSvuc `cat rsync-src-files` / mnt / d / rsync_test /

ИЛИ

rsync -aSvuc --recursive --files-from = rsync-src-files. / mnt / d / rsync_test /

Первая команда не требует пояснений, помимо содержимого файла, rsync-src-filesкоторое я подробно расскажу ниже. Теперь, если вы хотите использовать последнюю версию, вам нужно иметь в виду следующие четыре замечания:

  1. Обратите внимание, что нужно указать оба --files-fromи исходный каталог
  2. Уточнять нужно явно --recursive.
  3. Файл rsync-src-filesсоздан пользователем и помещен в каталог src для этого теста.
  4. Они rsyn-src-filesсодержат файлы и папки для копирования, и они берутся относительно исходного каталога. ВАЖНО: Убедитесь, что в файле нет конечных пробелов или пустых строк. В приведенном ниже примере всего две линии, а не три (это получается случайно). Содержание rsynch-src-files:

имя_папки1
имя_папки2

KF
источник
3

У меня аналогичная задача: выполнить синхронизацию всех файлов, измененных после указанной даты, но исключая некоторые каталоги. Было сложно создать один лайнер «все в одном», поэтому я разделил проблему на более мелкие части. Окончательное решение:

find  ~/sourceDIR -type f -newermt "DD MMM YYYY HH:MM:SS" | egrep -v "/\..|Downloads|FOO" > FileList.txt
rsync -v --files-from=FileList.txt ~/sourceDIR /Destination

Сначала пользуюсь find -L ~/sourceDIR -type f -newermt "DD MMM YYYY HH:MM:SS". Я попытался добавить regexв findстроку, чтобы исключить шаблоны имен, однако мой вкус Linux (Mint) не понимает отрицания регулярного выражения в find. Пробовал количество вариантов регулярных выражений - не работает по желанию. Таким образом, я получаю egrep -v- вариант, который исключает шаблон простым способом. My rsyncне копирует каталоги, такие как /.cache или /.config, а также некоторые другие, которые я явно назвал.

сопель
источник
1
Я считаю, что вы могли бы использовать замену процесса, чтобы превратить это в bashоднострочник:rsync -v --files-from=<(find ~/sourceDIR -type f -newermt "DD MMM YYYY HH:MM:SS" | grep -Ev "/\..|Downloads|FOO") ~/sourceDIR /Destination
phk
2
$ date
  Wed 24 Apr 2019 09:54:53 AM PDT
$ rsync --version
  rsync  version 3.1.3  protocol version 31
  ...

Синтаксис: rsync <file_/_folder_list> <source> <target>

Имена папок (здесь С завершающим /; например Cancer - Evolution/) находятся в файле списка папок (например: cm_folder_list_test):

# /mnt/Vancouver/projects/ie/claws/data/cm_folder_list_test
# test file: 2019-04-24
Cancer/
Cancer - Evolution/
Cancer - Genomic Variants/
Cancer - Metastasis (EMT Transition ...)/
Cancer Pathways, Networks/
Catabolism - Autophagy; Phagosomes; Mitophagy/
Catabolism - Lysosomes/

Если вы не /включите эти завершающие , целевые папки rsync'd будут созданы, но пусты.

Эти имена папок добавляются к остальной части их пути ( /home/victoria/Mail/2_RESEARCH - NEWS), таким образом обеспечивая полный путь к папке для rsync; например: /home/victoria/Mail/2_RESEARCH - NEWS/Cancer - Evolution/.

Обратите внимание, что вам также необходимо использовать --files-from=..., НЕ --include-from=...

rsync -aqP --delete --files-from=/mnt/Vancouver/projects/ie/claws/data/cm_folder_list_test "/home/victoria/Mail/2_RESEARCH - NEWS" $IN/

(В моем сценарии BASH я определил переменную $INследующим образом.)

BASEDIR="/mnt/Vancouver/projects/ie/claws"
IN=$BASEDIR/data/test/input

Используемые параметры rsync:

 -a  :   archive: equals -rlptgoD (no -H,-A,-X)
    -r  :   recursive
    -l  :   copy symlinks as symlinks
    -p  :   preserve permissions
    -t  :   preserve modification times 
    -g  :   preserve group 
    -o  :   preserve owner (super-user only) 
    -D  :   same as --devices --specials 
  -q  :   quiet (/server/547106/run-totally-silent-rsync)

  --delete
    This  tells  rsync to delete extraneous files from the RECEIVING SIDE (ones
    that AREN’T ON THE SENDING SIDE), but only for the directories that are
    being synchronized.  You must have asked rsync to send the whole directory
    (e.g.  "dir" or "dir/") without using a wildcard for the directory’s contents
    (e.g. "dir/*") since the wildcard is expanded by the shell and rsync thus
    gets a request to transfer individual files, not the files’ parent directory.
    Files  that  are  excluded  from  the transfer are also excluded from being
    deleted unless you use the --delete-excluded option or mark the rules as
    only matching on the sending side (see the include/exclude modifiers in the
    FILTER RULES section).  ...
Виктория Стюарт
источник
1

Этот ответ не является прямым ответом на вопрос. Но это должно помочь вам понять, какое решение лучше всего подходит для вашей проблемы.

При анализе проблемы следует активировать опцию отладки. -vv

Затем rsync выведет, какие файлы включены или исключены по какому шаблону:

building file list ... 
[sender] hiding file FILE1 because of pattern FILE1*
[sender] showing file FILE2 because of pattern *
Маттиас М
источник
0

Ни один из этих ответов не сработал для меня, когда у меня был только список каталогов . Тогда я наткнулся на решение! Вы должны добавить -rк, --files-fromпотому -aчто не будет рекурсивным в этом сценарии (кто знал ?!).

rsync -aruRP --files-from=directory.list . ../new/location
Теодор Р. Смит
источник
Если вы укажете «dir» в файле, вам необходимо указать -r / --recursive; если вы укажете «dir /», вы этого не сделаете.
lbutlr