Вопрос или проблема
Я пытаюсь применить метод из https://serverfault.com/a/788007/154366, но он каким-то образом не срабатывает.
Вот моя тестовая настройка:
#!/bin/bash
mkdir -p /tmp/test/{a/b,b/{a,b},c,.d}
touch /tmp/test/{f.txt,.f.txt,{a/b,b,b/{a,b},c,.d}/f.txt,b/.f.txt}
tree -a /tmp/test
/tmp/test
├── a
│ └── b
│ └── f.txt
├── b
│ ├── a
│ │ └── f.txt
│ ├── b
│ │ └── f.txt
│ ├── .f.txt
│ └── f.txt
├── c
│ └── f.txt
├── .d
│ └── f.txt
├── .f.txt
└── f.txt
Из /tmp/test
я хотел бы скопировать с помощью rsync -a
полную директорию ./a
, полную директорию ./b/b
, файлы и скрытые файлы, находящиеся на первом уровне в ./b
, а также файлы (не скрытые) на первом уровне в ./
.
Ожидаемые “копии” (обозначенные ->
) будут:
/tmp/test/ -> /tmp/filt/
/tmp/test/a/ -> /tmp/filt/a/
/tmp/test/a/b/ -> /tmp/filt/a/b/
/tmp/test/a/b/f.txt -> /tmp/filt/a/b/f.txt
/tmp/test/b/ -> /tmp/filt/b/
/tmp/test/b/a/
/tmp/test/b/a/f.txt
/tmp/test/b/b/ -> /tmp/filt/b/b/
/tmp/test/b/b/f.txt -> /tmp/filt/b/b/f.txt
/tmp/test/b/f.txt -> /tmp/filt/b/f.txt
/tmp/test/b/.f.txt -> /tmp/filt/b/.f.txt
/tmp/test/c/
/tmp/test/c/f.txt
/tmp/test/.d/
/tmp/test/.d/f.txt
/tmp/test/f.txt -> /tmp/filt/f.txt
/tmp/test/.f.txt
Поэтому я создал файл filter.txt
для rsync
:
+ /[!.]*
+ /a/
+ /a/**
+ /b/
+ /b/b/
+ /b/b/**
- /b/*/
+ /b/*
- /**
Но когда я пытаюсь это сделать:
rsync -av --dry-run --filter="merge filter.txt" /tmp/test /tmp/filt/
Я получаю:
sending incremental file list
test/
sent 74 bytes received 20 bytes 188.00 bytes/sec
total size is 0 speedup is 0.00 (DRY RUN)
примечание: ls /tmp/filt
выводит ошибку ls: cannot access /tmp/filt: No such file or directory
Что не так?
Ответ или решение
Использование rsync для копирования отдельных директорий и файлов
При использовании rsync
для копирования файлов и директорий может возникнуть необходимость исключить все, кроме нескольких специфичных каталогов и файлов. Давайте рассмотрим, как это адаптировать для вашей ситуации.
Проблемное Обозначение
У вас есть набор файлов и директорий в /tmp/test
, и вы хотите скопировать только определённые элементы в директорию /tmp/filt/
. Ваша цель состоит в том, чтобы включить следующие элементы:
- Полный каталог
./a
и все его содержимое. - Полный каталог
./b/b
и все его содержимое. - Файлы и скрытые файлы (dotfiles) в каталоге
./b
. - Файлы (не скрытые) в корневом каталоге
./
.
Если рассмотреть текущую реализацию через файл фильтрации filter.txt
, то нужно сделать несколько изменений, чтобы rsync
работал должным образом.
Файл filter.txt
Ваш файл filter.txt
имеет хорошую структуру, но требует нескольких корректировок для правильной работы. Вот исправленная версия:
+ /a/
+ /a/**
+ /b/
+ /b/b/
+ /b/b/**
+ /b/.*
+ /b/*
- /b/*/
- /**
Объяснение фильтров:
+ /a/
– включает полный каталогa
.+ /a/**
– включает все содержимое внутри каталогаa
.+ /b/
– включает каталогb
.+ /b/b/
– включает каталогb/b
.+ /b/b/**
– включает все внутри каталогаb/b
.+ /b/.*
– включает все скрытые файлы в каталогеb
.+ /b/*
– включает все обычные файлы в каталогеb
.- /b/*/
– исключает все подкаталоги в каталогеb
.- /**
– исключает все остальное содержимое.
Использование rsync
Теперь, чтобы выполнить вашу задачу, можете использовать следующую команду rsync
:
rsync -av --dry-run --filter="merge /path/to/filter.txt" /tmp/test/ /tmp/filt/
Разбор команды
-a
– это архивный режим, который сохраняет права и временные метки.-v
– включает подробный режим, что помогает увидеть, какие файлы передаются.--dry-run
– позволяет протестировать команду без фактического выполнения операции, что полезно для проверки корректности настроек.--filter
– указывает на файл с фильтрами, которые будут применены при копировании.
Итоги
После внесения корректировок в файл фильтрации и правильного использования команды rsync
вы сможете достичь желаемого результата. Применяя вышеуказанные указания, вы сможете скопировать только те файлы и каталоги, которые вам нужны, при этом исключив все остальные.
Если после выполнения команды rsync
с изменённым фильтром все ещё возникают вопросы, не стесняйтесь задавать их для получения дополнительной информации и помощи.