rsync копіює лише певні типи файлів, використовуючи опцію include


110

Я використовую наступний скрипт bash, щоб копіювати лише файли певного розширення (у цьому випадку * .sh), однак він все ще копіює всі файли. що не так?

від = 1 дол
до = 2 дол

rsync -zarv --include = "*. sh" $ від $ до

4
Хоча це не суворо кажучи, я б запропонував цитувати $ від / $ до. Якщо цього не зробити, ви можете отримати несподівані результати, якщо позиційні аргументи 1/2 включають пробіли.
Kjetil Joergensen

Ви зрозуміли, чому ваша команда не буде просто працювати?
Чарлі Паркер

@CharlieParker: Вам доводиться використовувати rsync, це дуже добре можна досягти за допомогою внутрішніх оболонок?
Ініан

Чого цього питання та його відповідей також не вистачає, як скласти команду, якщо у мене є рекурсивні каталоги, які я хочу надіслати лише одного типу файлів. Здається, це робиться лише для цільового каталогу ...
Чарлі Паркер

Відповіді:


200

Я думаю --include, що використовується для включення підмножини файлів, які інакше виключені --exclude, а не включають лише ті файли. Іншими словами: ви повинні подумати про включення значення , яке не виключайте .

Спробуйте замість цього:

rsync -zarv  --include "*/" --exclude="*" --include="*.sh" "$from" "$to"

Для rsync версії 3.0.6 або новішої, замовлення потрібно змінити наступним чином (див. Коментарі):

rsync -zarv --include="*/" --include="*.sh" --exclude="*" "$from" "$to"

Додавання -mпрапора дозволить уникнути створення порожніх структур каталогів у пункті призначення. Тестовано у версії 3.1.2.

Отже, якщо ми хочемо лише * .sh файлів, ми повинні виключити всі файли --exclude="*", включити всі каталоги --include="*/"та включити всі * .sh файли --include="*.sh".

Ви можете знайти кілька хороших прикладів у розділі Включити / виключити правила використання шаблону сторінки людини


10
Хоча ви отримаєте всі підкаталоги, якщо в підкаталогах, які ви хочете rsync, є будь-які .sh файли, ймовірно, ви також хочете використовувати --include = "* /".
Kjetil Joergensen

50
Я спробував це на версії rsync 3.0.7, яку я отримав давно від макпортів, і вона не працювала з цим упорядкуванням включає / виключає. Це те , що я закінчив з , що працював для мене (адаптовано для OP): rsync -zarv --include="*/" --include="*.sh" --exclude="*" "$from" "$to".
Біжу Трувей

3
Я спробував з rsync 3.0.9, і це не спрацювало. Біжу має рацію, замовлення не належне (спочатку --include=\*.shпотім --exclude=\*)
TrueY

3
Зауважте, що ви завжди можете натиснути редагувати та запропонувати редагувати відповідь :)
Ахал Дейв

2
Це не працює з вашим упорядкуванням включає / виключає, але працює з замовленням, запропонованим Біжу Трувей
Джон Сміт Необов’язково

57

Відповідь @chepner буде копіювати всі підкаталоги незалежно від того, чи містить він файл чи ні. Якщо вам потрібно виключити підкаталоги, які не містять файл і все ще зберігають структуру каталогу, використовуйте

rsync -zarv  --prune-empty-dirs --include "*/"  --include="*.sh" --exclude="*" "$from" "$to"

1
Ця вимога була для мене: "Якщо вам потрібно виключити підкаталоги, які не містять файл і все ще зберігають структуру каталогів" +1
Juuso Ohtonen

1
Я не розумію, як ти знав, яким був порядок - входить?
Чарлі Паркер

1
Як можна виконати команду, якщо у мене є рекурсивні каталоги, які я хочу надіслати лише одного типу файлів. Здається, це робиться лише для цільового каталогу.
Чарлі Паркер

15

Ще одне доповнення: якщо вам потрібно синхронізувати файли за його розширеннями лише в одному dir (без рекурсії), ви повинні використовувати конструкцію, як це:

rsync -auzv --include './' --include '*.ext' --exclude '*' /source/dir/ /destination/dir/

У першу чергу зверніть увагу на крапку --include. --no-rне працює в цій конструкції.

Редагувати:

Дякуємо gbyte.co за цінний коментар!


1
як ви знали, яким повинен бути порядок прапорів і що вони повинні включати?
Чарлі Паркер

1
@CharlieParker, оскільки rsync використовує параметри includeта excludeпараметри в тому порядку, в якому вони були вказані. Крім цього, він зупиняється на першому зібраному. Отже, якщо ми --exclude '*'в цьому прикладі вкажемо перше місце, rsync нічого не зробить. Додаткових пояснень дивіться у чоловіка.
Серж Руссак

ви можете мені пояснити, що робить кожен прапор? Перший прапор -- include './' говорить: включити все в шлях до вихідного каталогу? Тоді наступне `--include '.ext'` включати конкретний файл у вихідний шлях з ім'ям, .extа потім виключення говорить не надсилати нічого іншого --exclude '*'? Це правильно?
Чарлі Паркер

1
Як можна виконати команду, якщо у мене є рекурсивні каталоги, які я хочу надіслати лише одного типу файлів. Здається, це робиться лише для цільового каталогу.
Чарлі Паркер

1
Дякую за це! Потрібно --include '*.ext'і не--include '.ext'
гбайт

13

Ось важлива частина сторінки man:

Оскільки список файлів / каталогів для передачі складається, rsync перевіряє кожне ім'я, яке потрібно перенести, зі списком шаблонів включати / виключати по черзі, і діяє перший узор відповідності: якщо це шаблон виключення, то цей файл є пропустив; якщо це шаблон включення, це ім'я файлу не пропускається; якщо не знайдено відповідного шаблону, то ім'я файлу не пропускається.

Узагальнити:

  • Невідповідність жодному шаблону означає, що файл буде скопійовано!
  • Алгоритм закриває один раз будь-який шаблон

Крім того, щось, що закінчується косою рисою, - це відповідність каталогів (як find -type dби).

Давайте розв’яжемо цю відповідь зверху.

rsync -zarv  --prune-empty-dirs --include "*/"  --include="*.sh" --exclude="*" "$from" "$to"
  1. Не пропускайте жодних каталогів
  2. Не пропускайте жодні .shфайли
  3. Пропустити все
  4. (Послідовно, не пропускайте нічого, але вищевказане правило запобігає тому, щоб правило за замовчуванням не відбувалося.)

Нарешті, --prune-empty-directoriesутримує перше правило - робити порожні каталоги всюди.


Дуже дякую за пояснення того, що відбувається. Тепер є набагато більший шанс, що я не забуду команду.
MohamedEzz

3
«» Алгоритм квити коли шаблон відповідає » - це ключ, і жоден з вищих рейтингової оцінки відповідей не пояснює , як ясно і до фронту , як ви зробили тут , звичайно це. Є в довідковій сторінці somehwere, і якщо я Я прочитав би все це уважно, я б це бачив. Все-таки дякую
TheDudeAbides

0

Якщо хтось шукає цього… Я хотів rsync лише певні файли та папки і мені вдалося це зробити за допомогою цієї команди: rsync --include-from=rsync-files

З rsync-файлами:

my-dir/
my-file.txt

- /*

0

Написав цю зручну функцію і помістив у мої сценарії bash або ~/.bash_aliases. Випробувано синхронізацію локально на Linux з bash та awkвстановлено. Це працює

selrsync(){
# selective rsync to sync only certain filetypes;
# based on: https://stackoverflow.com/a/11111793/588867
# Example: selrsync 'tsv,csv' ./source ./target --dry-run
types="$1"; shift; #accepts comma separated list of types. Must be the first argument.
includes=$(echo $types| awk  -F',' \
    'BEGIN{OFS=" ";}
    {
    for (i = 1; i <= NF; i++ ) { if (length($i) > 0) $i="--include=*."$i; } print
    }')
restargs="$@"

echo Command: rsync -avz --prune-empty-dirs --include="*/" $includes --exclude="*" "$restargs"
eval rsync -avz --prune-empty-dirs --include="*/" "$includes" --exclude="*" $restargs
}

Переваги:

короткий зручний і розширюваний, коли хочеться додати більше аргументів (тобто --dry-run).

Приклад:

selrsync 'tsv,csv' ./source ./target --dry-run
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.