Как «отменить» rsync -L?

Из документов для флага rsync -L :

-L, –copy-links преобразуют символическую ссылку в файл-референт / dir

Этот вопрос касается того, как «отменить» передачу, которая была первоначально выполнена с помощью rsync -L ...


Мне легче всего объяснить, что я имею в виду здесь, «обратным» с простым конкретным примером.

Настройка

Предположим, что у меня есть каталоги /tmp/SOURCE/ и /tmp/TARGET/ , как показано ниже:

 $ /usr/bin/tree -aF /tmp/SOURCE/ /tmp/TARGET/ /tmp/SOURCE/ ├── Ad/ │  ├── w │  └── x ├── Bd/ │  └── z ├── Cd/ │  ├── w -> ../Ad/w │  └── y -> ../Ad/x └── Dl -> Bd/ /tmp/TARGET/ 

В частности, обратите внимание на следующие детали:

  • содержимое /tmp/SOURCE/Cd – относительные символические ссылки, указывающие на обычные файлы в /tmp/SOURCE/Ad ;
    • базовые имена symlink /tmp/SOURCE/Cd/w и его реферата одинаковы;
    • базовые имена symlink /tmp/SOURCE/Cd/y (а именно y ) и его референта (а именно, x ) различны;
  • /tmp/SOURCE/Dl – относительная символическая ссылка на /tmp/SOURCE/Bd ;
  • /tmp/TARGET/ в настоящее время пуст.

Из этого начального состояния я запускаю вид commmand, упомянутый в заголовке этого сообщения, такую ​​команду, которую я хочу «отменить» (как объясняется ниже):

 $ rsync -L -a /tmp/SOURCE/Cd /tmp/SOURCE/Dl /tmp/TARGET 

После выполнения этой команды /tmp/TARGET/ выглядит следующим образом:

 $ /usr/bin/tree -aF /tmp/TARGET/ /tmp/TARGET/ ├── Cd/ │  ├── w │  └── y └── Dl/ └── z 

Обратите внимание, в частности, что, хотя в обоих случаях /tmp/SOURCE и /tmp/TARGET относительные пути

 Cd/w Cd/y Dl/z 

существуют, только те, что находятся в /tmp/TARGET являются «реальными» путями. По «реальному пути» $P я имею в виду, что, грубо говоря, вывод readlink -f $P снова равен $P (или, точнее, ${P:a} ). Например

 $ readlink -f /tmp/TARGET/Cd/w /tmp/TARGET/Cd/w 

но

 $ readlink -f /tmp/SOURCE/Cd/w /tmp/SOURCE/Ad/w 

Проблема

В текущем контексте, что я подразумеваю под «реверсированием» предыдущей команды rsync -L в основном, нужно скопировать обычные файлы в /tmp/TARGET/ на их оригиналы в /tmp/SOURCE , оставив структуру /tmp/SOURCE без изменений.

В частности, после этой «обратной передачи» символические ссылки в /tmp/SOURCE должны оставаться символическими ссылками и должны указывать на то же самое, что и раньше.

Я ищу способ выполнить такую ​​«разворот», которая сопоставима по сложности / сложности с командой rsync -aL используемой для выполнения «прямой» передачи в первую очередь.


Один из недостатков этого простого примера состоит в том, что он настолько прост, что у вас возникает соблазн решить проблему с помощью грубой силы. Например

 $ rsync /tmp/TARGET/Cd/w /tmp/SOURCE/Ad $ rsync /tmp/TARGET/Cd/y /tmp/SOURCE/Ad/x $ rsync /tmp/TARGET/Dl/z /tmp/SOURCE/Bd 

IOW, в такой простой ситуации этот подход грубой силы не намного сложнее, чем запуск оригинальной передачи rsync -L . В целом, однако, стратегия грубой силы может быть значительно сложнее выполнить по сравнению с первоначальной передачей.

Этот пример упрощен также потому, что исходный и целевой хосты одинаковы. В общем, их не будет, поэтому, пожалуйста, избегайте решений, которые полагаются на эту особенность примера.


FWIW, следующий сценарий создает настройку примера игрушек выше.

 BASEDIR=/tmp/test1 # uncomment the following line before running this script a second time # rm -rf $BASEDIR/SOURCE $BASEDIR/TARGET mkdir -p $BASEDIR/SOURCE/{A,B,C}.d $BASEDIR/TARGET touch $BASEDIR/SOURCE/{Ad/{w,x},Bd/z} ln -s ../Ad/w $BASEDIR/SOURCE/Cd/w ln -s ../Ad/x $BASEDIR/SOURCE/Cd/y ln -s Bd $BASEDIR/SOURCE/Dl 

2 Solutions collect form web for “Как «отменить» rsync -L?”

Существуют опции, позволяющие rsync не беспокоить символические ссылки на удаленном компьютере, если они ссылаются на каталоги, но у него нет возможности не заменять символические ссылки на файлы с помощью реальных файлов.

Так что вы можете сначала сохранить символические ссылки на файлы в SOURCE каким-либо образом, например, переименовав их или перечислив их в файл, затем сохраните символические ссылки каталога rsync, затем восстановите символические ссылки файла, скопировав данные из реальный файл к восстановленной символической ссылке, а затем удаление реального файла. Вот потенциальный сценарий:

 find /tmp/SOURCE -type l ! -xtype d -exec mv {} {}.lnk \; cd /tmp/TARGET || exit rsync -a -R --no-implied-dirs --keep-dirlinks . /tmp/SOURCE/ find /tmp/SOURCE -type l ! -xtype d | while read fname do base=${fname%.lnk} cp "$base" "$fname" mv "$fname" "$base" done 

Я оставляю вас правильно справляться со странными именами файлов. Я не уверен, что необходимы -R --no-implied-dirs , но я позволю вам поэкспериментировать с этим.

Я не думаю, что вы можете сделать это прямо в rsync . Параметр --keep-dirlinks ( -K ) сохраняет ссылки на симлинк-каталоги нетронутыми, но символические файлы все равно будут перезаписаны.

Самое близкое решение, которое я могу найти для этого, – это небольшой скрипт ( bash )

 ( cd TARGET && find . -type f -print0 | sed 's!^./!!' ) | while IFS= read -d $'\0' -rf do s=$(readlink -f SOURCE/"$f") rsync -a TARGET/"$f" "${s:-f}" done 

Это берет каждый файл в TARGET одному за раз, проверяет цель symlink в SOURCE и напрямую применяет rsync к этому.

  • Как я могу вывести «временно» в оболочку, как это делает завершение вкладки zsh?
  • перенаправление ввода-вывода zsh: перенаправление и последующее соединение; что происходит?
  • Возможно ли возобновить источник .bashrc и .zshrc И удалить функции один раз внутри них без перезапуска?
  • Как проверить параметр zsh-скрипта в шаблоне или нет?
  • Zsh auto complete предлагает полные функции (_git _vim и т. Д.)
  • индикатор выполнения, чтобы узнать, сколько выполнено выход скрипта оболочки
  • Есть ли способ сохранить команду в вашей истории?
  • Альтернатива bash `history -p` в zsh?
  • Объединение команды, включающей одиночные и двойные кавычки для другой команды
  • Завершение Zsh для монтирования (/ run / media / DISK-LABEL)?
  • Заполнение ZSH с помощью команды output
  • Linux и Unix - лучшая ОС в мире.