Как скопировать структуру каталогов, но включить только определенные файлы - PullRequest
3 голосов
/ 26 сентября 2011

Я нашел решение для моего вопроса в Windows, но я использую Ubuntu: Как скопировать структуру каталогов, но включить только определенные файлы, используя пакетные файлы Windows?

В качестве заголовкаговорит, как я могу рекурсивно копировать структуру каталогов, но включать только некоторые файлы?Например, с учетом следующей структуры каталогов:

folder1
  folder2
    folder3
      data.zip
      info.txt
      abc.xyz
    folder4
    folder5
      data.zip
      somefile.exe
      someotherfile.dll

Файлы data.zip и info.txt могут появляться везде в структуре каталогов.Как я могу скопировать полную структуру каталогов, но включить только файлы с именами data.zip и info.txt (все остальные файлы следует игнорировать)?

Полученная структура каталогов должна выглядеть следующим образом:

copy_of_folder1
  folder2
    folder3
      data.zip
      info.txt
    folder4
    folder5
      data.zip

Не могли бы вы сказать мне решение для Ubuntu?

Ответы [ 4 ]

4 голосов
/ 03 ноября 2015
$ rsync --recursive --include="data.zip" --include="*.txt" --filter="-! */" dir_1 copy_of_dir_1

Чтобы исключить dir3 независимо от того, где оно находится в дереве (даже если оно содержит файлы, соответствующие --include с):

--exclude 'dir3/' (before `--filter`)

Чтобы исключить dir3 только в определенном месте дерева, укажите абсолютный путь, начиная с исходного каталога:

--exclude '/dir1/dir2/dir3/' (before `--filter`)

Чтобы исключить dir3 только тогда, когда он находится в dir2, но независимо от того, где dir2:

--exclude 'dir2/dir3/' (before `--filter`)

Подстановочные знаки также могут использоваться в элементах пути, где * означает каталог с любым именем, а ** означает несколько вложенных каталогов.

Чтобы указать только файлы и каталоги для включения, запустите два rsync s, один для файлов и один для каталогов. Проблема с выполнением этого в одном rsync заключается в том, что когда вы не включаете dir, rsync не будет входить в dir и, следовательно, не обнаружит никаких файлов в этой ветви, которые могут соответствовать вашему фильтру включения. , Итак, вы начинаете с копирования файлов, которые вы хотите, не создавая никаких каталогов, которые были бы пустыми. Затем скопируйте все нужные вам каталоги.

$ rsync --recursive --prune-empty-dirs --include="*.txt" --filter="-! */" dir_1 copy_of_dir_1
$ rsync --recursive --include '/dir1/dir2/' --include '/dir3/dir4/' --filter="-! */" dir_1 copy_of_dir_1

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

$ rsync --recursive --prune-empty-dirs --include="*.txt" --include '/dir1/dir2/' --include '/dir3/dir4/' --filter="-! */" dir_1 copy_of_dir_1

--filter="-! */" необходим, потому что rsync включает все файлы и папки, которые не соответствуют ни одному из фильтров (представьте его как невидимый --include фильтр в конце списка фильтров). rsync проверяет каждый элемент для копирования по списку фильтров и включает или исключает элемент в зависимости от первого найденного совпадения. Если совпадения нет, он попадает в невидимое --include и продолжает включать предмет. Мы хотели изменить это значение по умолчанию на --exclude, поэтому мы добавили фильтр исключения (- в -! */), затем мы отменяем совпадение (!) и сопоставляем все каталоги (*/). Поскольку это отрицательное совпадение, в результате мы разрешаем rsync вводить все каталоги (что, как я упоминал ранее, позволяет rsync находить нужные нам файлы).

Мы используем --filter вместо --exclude для окончательного фильтра, потому что --exclude не позволяет указывать отрицательные совпадения с оператором !.

1 голос
/ 06 ноября 2015

Вот однострочник, использующий rsync:

 rsync -a -f"+ info.txt" -f"+ data.zip" -f'-! */' folder1/ copy_of_folder1/

Если у вас уже есть список файлов и вы хотите более масштабируемое решение

 cat file.list | xargs -i rsync -a -f"+ {}" -f'-! */' folder1/ copy_of_folder1/
1 голос
/ 26 сентября 2011

У меня нет красивого лайнера, но так как никто больше не ответил, вы всегда можете:

find . -name 'file_name.extension' -print | cpio -pavd /path/to/receiving/folder

Для каждого конкретного файла после копирования каталогов.

(Убедитесь, чтоВы, конечно, сначала в исходной папке! :))

0 голосов
/ 03 ноября 2015
cp -pr folder1 copy_of_folder1; find copy_of_folder1 -type f ! \( -name data.zip -o -name info.txt \)  -exec rm -f {} \;
  • в первый раз: скопировать полностью folder1 в copy_of_folder1
  • во второй раз: удалить все файлы, отличающиеся от data.zip и info.txt
  • В конце у вас естьВаша полная структура с использованием только файла data.zip и info.txt
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...