Вопрос или проблема
Я пытаюсь использовать опцию --delete
в rsync
, чтобы удалить файлы в целевом каталоге, которые отсутствуют в исходном каталоге
Вот команда, которую я использую:
rsync -avz --ignore-existing --recursive --delete /var/www/* [email protected]:/var/www
Так что мой вопрос в том, как я могу удалить все файлы в целевом каталоге, которые отсутствуют в исходном каталоге?
Используйте эту команду:
rsync --archive --verbose --compress --ignore-existing --delete /var/www/ [email protected]:/var/www
Вам не нужен символ “*” и не следует его использовать.
Чтобы исключить/включить файлы или каталоги, вы должны использовать эти параметры:
--exclude 'to_exclude*'
--include 'to_include*'
Ваша команда не работала, потому что, когда вы использовали /var/www/*
в качестве источника, ваша оболочка выполняет расширение паттерна, т.е. оболочка расширяет *
на все файлы в этом каталоге и копирует файлы по одному, так что отдельные файлы становятся источниками, а не родительским каталогом.
Так что, если вы используете /var/www/*
, то вам не нужна опция --recursive
, так как *
вызовет копирование файлов (вместе с любыми каталогами с их содержимым), а не родительского каталога, который содержит файлы. По той же причине --delete
не работает, так как --delete
удалит файлы из целевого каталога, которые отсутствуют в исходном каталоге, но вы копируете файлы, поэтому он не удаляет файлы (как ожидалось).
Это сделает вам более ясно:
/foo$ ls -l
-rw-rw-r-- 1 user user 0 Apr 16 17:56 egg
-rw-rw-r-- 1 user user 0 Apr 16 17:56 spam
drwxrwxr-x 2 user user 4096 Apr 16 18:14 test
/bar$ ls -l
-rw-rw-r-- 1 user user 0 Apr 16 17:56 egg
-rw-rw-r-- 1 user user 0 Apr 16 18:13 lion
-rw-rw-r-- 1 user user 0 Apr 16 17:56 spam
$ rsync -avz --ignore-existing --recursive --delete
/foo/* /bar/
+ rsync -avz --ignore-existing --recursive --delete
/foo/egg /foo/spam /foo/test /bar/
sending incremental file list
test/
test/hello
sent 173 bytes received 39 bytes 424.00 bytes/sec
total size is 0 speedup is 0.00
/bar$ ls -l
-rw-rw-r-- 1 user user 0 Apr 16 17:56 egg
-rw-rw-r-- 1 user user 0 Apr 16 18:13 lion
-rw-rw-r-- 1 user user 0 Apr 16 17:56 spam
drwxrwxr-x 2 user user 4096 Apr 16 18:14 test
Как видите, я использовал источник как /foo/*
, таким образом выполняется команда rsync
rsync -avz --ignore-existing --recursive --delete /foo/egg
/foo/spam /foo/test /bar/
с *
, заставляющим оболочку расширять его и делать все файлы индивидуально источниками, а не родительский каталог целиком (и вам также не нужна --recursive
в этом случае).
Так что, если вы хотите, чтобы --delete
работало, выполните это так:
rsync -avz --ignore-existing --recursive --delete
/var/www/ [email protected]:/var/www/
Ответ или решение
Проблема: Опция --delete
в rsync
не удаляет файлы в целевом каталоге
Введение
Команда rsync
является мощным инструментом для синхронизации файлов и каталогов между локальными и удалёнными системами. Однако иногда пользователи сталкиваются с проблемами, связанными с опцией --delete
, которая предназначена для удаления файлов в целевом каталоге, отсутствующих в исходном каталоге. В данной статье мы подробно рассмотрим, почему опция --delete
может не работать в вашем случае и как правильно использовать команду rsync
.
Описание проблемы
Вы используете следующую команду:
rsync -avz --ignore-existing --recursive --delete /var/www/* user@remote:/var/www
Ваша цель — удалить файлы в целевом каталоге /var/www
на удалённом сервере, которые не присутствуют в локальном каталоге /var/www
. Однако, как вы заметили, выполнение данной команды не приводит к удалению ожидаемых файлов.
Причина неработоспособности
Ключевым моментом вашей команды является использование шаблона *
:
- Использование
/var/www/*
ведет к тому, что оболочка (shell) расширяет данный шаблон в список всех файлов и каталогов в директории/var/www
. - В результате,
rsync
обрабатывает каждый файл и каталог как отдельный аргумент, вместо того чтобы рассматривать весь каталогvar/www
в целом. Это находит отражение в том, что--delete
не может корректно определить файлы для удаления.
Когда вы передаете файлы как отдельные аргументы, rsync
сравнивает их с содержимым целевого каталога и не применяет удаление, поскольку по сути вы не указываете исходный каталог, а всего лишь конкретные файлы.
Решение проблемы
Чтобы исправить ситуацию и обеспечить работу опции --delete
, вам нужно изменить синтаксис команды. Уберите звездочку (*
) и добавьте завершающий слэш к исходному каталогу. Ваш исправленный вызов команды будет выглядеть так:
rsync -avz --ignore-existing --delete /var/www/ user@remote:/var/www/
Объяснение изменений:
- Использование
/var/www/
(с завершающим слэшем) указываетrsync
, что необходимо синхронизировать содержимое каталога, вместо обработки отдельных файлов. - Удаление опции
--recursive
в данном случае не требуется, поскольку, когда указаны директории,rsync
по умолчанию работает рекурсивно.
Дополнительные настройки
Если вам необходимо исключить или включить определенные файлы и каталоги, для этого подойдут параметры --exclude
и --include
. Например:
rsync -avz --delete --exclude 'to_exclude*' --include 'to_include*' /var/www/ user@remote:/var/www/
Заключение
Использование команды rsync
может показаться сложным на первый взгляд, особенно с множеством доступных опций. Ваша проблема с отсутствием удаления файлов в целевом каталоге была вызвана неверным указанием исходного каталога. Внедрение нескольких изменений в ваш первоначальный синтаксис позволит вам успешно использовать опцию --delete
и поддерживать актуальность данных между локальным и удалённым каталогами.