rsync копирует только определенные типы файлов с помощью опции включения
110
Я использую следующий сценарий bash для копирования только файлов определенного расширения (в данном случае * .sh), однако он по-прежнему копирует все файлы. в чем дело?
от = $ 1
to = $ 2
rsync -zarv --include = "*. sh" $ от $ до
Хотя это, строго говоря, не связано, я бы предложил процитировать $ from / $ to. Невыполнение этого может привести к неожиданным результатам, если позиционные аргументы 1/2 содержат пробелы.
Kjetil Joergensen
Вы поняли, почему ваша команда просто не работает?
Чарли Паркер
@CharlieParker: Вы должны использовать rsync, это вполне может быть достигнуто с помощью внутренних компонентов оболочки?
Inian
Чего также не хватает в этом вопросе и ответах на него, так это о том, как создать команду, если у меня есть рекурсивные каталоги, в которые я хочу отправить только один тип файла. Похоже, это работает только с целевым каталогом ...
Чарли Паркер
Ответы:
200
Я думаю, что --includeиспользуется для включения подмножества файлов, которые в противном случае исключаются --exclude, а не для включения только этих файлов. Другими словами: вы должны думать о включении значения , а не об исключении .
Добавление -mфлага позволит избежать создания пустых структур каталогов в месте назначения. Проверено в версии 3.1.2.
Поэтому, если нам нужны только файлы * .sh, мы должны исключить все файлы --exclude="*", включить все каталоги --include="*/"и включить все файлы * .sh --include="*.sh".
Вы можете найти несколько хороших примеров в разделе « Правила включения / исключения шаблонов» на странице руководства.
Хотя он предоставит вам все подкаталоги, если в подкаталогах, которые вы хотите использовать rsync, есть какие-либо файлы .sh, скорее всего, вы тоже захотите использовать --include = "* /".
Kjetil Joergensen
50
Я пробовал это на rsync версии 3.0.7, которую я давно получил от macports, и это не сработало с таким порядком включения / исключения. Это то , что я закончил с , что работал для меня (адаптировано для OP): rsync -zarv --include="*/" --include="*.sh" --exclude="*" "$from" "$to".
Bijou Trouvaille
3
Я пробовал использовать rsync 3.0.9, но ничего не вышло. Бижу прав, упорядочение не является правильным (первым --include=\*.shтогда --exclude=\*)
TrueY
3
Обратите внимание, что вы всегда можете нажать кнопку «Изменить» и предложить
исправление
2
Он не работает с вашим порядком включения / исключения, но он работает с порядком, предложенным Бижу Трувай
Джон Смит Необязательно
57
Ответ @chepner скопирует все подкаталоги независимо от того, содержит ли он файл или нет. Если вам нужно исключить подкаталоги, которые не содержат файл, но при этом сохраняют структуру каталогов, используйте
Для меня это было требованием: «Если вам нужно исключить подкаталоги, которые не содержат файл, и при этом сохранить структуру каталогов» +1
Юусо Охтонен
1
Я не понимаю, как вы узнали, в каком порядке были включения?
Чарли Паркер
1
Как создать команду, если у меня есть рекурсивные каталоги, в которые я хочу отправить только один тип файла. Кажется, это только для целевого каталога.
Чарли Паркер
15
Еще одно дополнение: если вам нужно синхронизировать файлы по их расширениям только в одном каталоге (без рекурсии), вы должны использовать такую конструкцию:
как вы узнали, в каком порядке должны быть флаги и что они должны были включать?
Чарли Паркер
1
@CharlieParker, потому что rsync использует параметры includeи excludeв том порядке, в котором они были указаны. В дополнение к этому он останавливается на первом подходящем. Итак, если мы укажем --exclude '*'на первом месте в этом примере, rsync ничего не сделает. См. Этого человека для получения дополнительных объяснений.
Serge Roussak
вы можете мне объяснить, что делает каждый флаг? Первый флаг -- include './' говорит включить все в путь к исходному каталогу? Затем следующий `--include '.ext' 'включает конкретный файл в указанный исходный путь, .extа затем исключение говорит, что больше ничего не отправлять --exclude '*'? Это правильно?
Чарли Паркер
1
Как создать команду, если у меня есть рекурсивные каталоги, в которые я хочу отправить только один тип файла. Кажется, это только для целевого каталога.
Чарли Паркер,
1
Спасибо за это! Потребности в --include '*.ext'и не--include '.ext'
Гбайта
13
Вот важная часть справочной страницы:
По мере создания списка файлов / каталогов для передачи rsync по очереди проверяет каждое передаваемое имя на соответствие списку шаблонов включения / исключения, и действует первый соответствующий шаблон: если это шаблон исключения, то этот файл пропущено; если это шаблон включения, то это имя файла не пропускается; если соответствующий шаблон не найден, имя файла не пропускается.
Подвести итоги:
Отсутствие совпадения с шаблоном означает, что файл будет скопирован!
Алгоритм завершает работу при совпадении любого шаблона
Кроме того, что-то, заканчивающееся косой чертой, соответствует каталогам (например find -type d,).
Большое спасибо за объяснение того, что происходит. Теперь гораздо больше шансов, что я не забуду команду.
MohamedEzz
3
«Алгоритм завершает работу, когда какой-либо шаблон соответствует» - это ключевой момент, и ни один из ответов с более высоким рейтингом не объясняет его так четко и открыто, как вы сделали здесь. Конечно, это есть на странице руководства где-то, и если я Прочитал бы все внимательно, я бы это увидел. Тем не менее, спасибо.
TheDudeAbides
0
Если кто-то ищет это ... Я хотел выполнить синхронизацию только определенных файлов и папок, и мне удалось сделать это с помощью этой команды: rsync --include-from=rsync-files
Написал эту удобную функцию и вставил в свои сценарии bash или ~/.bash_aliases. Протестировано синхронизацию локально в Linux с awkустановленным bash . Оно работает
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).
rsync
, это вполне может быть достигнуто с помощью внутренних компонентов оболочки?Ответы:
Я думаю, что
--include
используется для включения подмножества файлов, которые в противном случае исключаются--exclude
, а не для включения только этих файлов. Другими словами: вы должны думать о включении значения , а не об исключении .Вместо этого попробуйте:
Для версии rsync 3.0.6 или выше порядок необходимо изменить следующим образом (см. Комментарии):
Добавление
-m
флага позволит избежать создания пустых структур каталогов в месте назначения. Проверено в версии 3.1.2.Поэтому, если нам нужны только файлы * .sh, мы должны исключить все файлы
--exclude="*"
, включить все каталоги--include="*/"
и включить все файлы * .sh--include="*.sh"
.Вы можете найти несколько хороших примеров в разделе « Правила включения / исключения шаблонов» на странице руководства.
источник
rsync -zarv --include="*/" --include="*.sh" --exclude="*" "$from" "$to"
.--include=\*.sh
тогда--exclude=\*
)Ответ @chepner скопирует все подкаталоги независимо от того, содержит ли он файл или нет. Если вам нужно исключить подкаталоги, которые не содержат файл, но при этом сохраняют структуру каталогов, используйте
источник
Еще одно дополнение: если вам нужно синхронизировать файлы по их расширениям только в одном каталоге (без рекурсии), вы должны использовать такую конструкцию:
Обратите внимание на точку в первом
--include
.--no-r
не работает в этой конструкции.РЕДАКТИРОВАТЬ:
Спасибо gbyte.co за ценный комментарий!
источник
include
иexclude
в том порядке, в котором они были указаны. В дополнение к этому он останавливается на первом подходящем. Итак, если мы укажем--exclude '*'
на первом месте в этом примере, rsync ничего не сделает. См. Этого человека для получения дополнительных объяснений.-- include './'
говорит включить все в путь к исходному каталогу? Затем следующий `--include '.ext' 'включает конкретный файл в указанный исходный путь,.ext
а затем исключение говорит, что больше ничего не отправлять--exclude '*'
? Это правильно?--include '*.ext'
и не--include '.ext'
Вот важная часть справочной страницы:
Подвести итоги:
Кроме того, что-то, заканчивающееся косой чертой, соответствует каталогам (например
find -type d
,).Давайте разберем этот ответ сверху.
.sh
файлыНаконец,
--prune-empty-directories
первое правило не допускает создания пустых каталогов повсюду.источник
Если кто-то ищет это ... Я хотел выполнить синхронизацию только определенных файлов и папок, и мне удалось сделать это с помощью этой команды:
rsync --include-from=rsync-files
С rsync-файлами:
источник
Написал эту удобную функцию и вставил в свои сценарии bash или
~/.bash_aliases
. Протестировано синхронизацию локально в Linux сawk
установленным bash . Оно работаетПреимущества:
короткий, удобный и расширяемый, когда нужно добавить больше аргументов (т.е.
--dry-run
).Пример:
источник