Nos documentos do rsync
' -L
flag:
-L, --copy-links transform symlink into referent file/dir
Esta questão é sobre como "reverter" uma transferência que foi feita originalmente usando rsync -L ...
.
É mais fácil para mim explicar o que quero dizer aqui "invertendo" com um simples exemplo concreto.
A configuração
Suponha que eu tenha diretórios /tmp/SOURCE/
e /tmp/TARGET/
, conforme mostrado abaixo:
$ /usr/bin/tree -aF /tmp/SOURCE/ /tmp/TARGET/
/tmp/SOURCE/
├── A.d/
│ ├── w
│ └── x
├── B.d/
│ └── z
├── C.d/
│ ├── w -> ../A.d/w
│ └── y -> ../A.d/x
└── D.l -> B.d/
/tmp/TARGET/
Em particular, observe os seguintes detalhes:
- o conteúdo de
/tmp/SOURCE/C.d
são links simbólicos relativos a arquivos regulares em /tmp/SOURCE/A.d
;
- os nomes básicos de symlink
/tmp/SOURCE/C.d/w
e de seus referentes são os mesmos;
- os nomes básicos de symlink
/tmp/SOURCE/C.d/y
(a saber, y
) e de seu referente (a saber, x
) são diferentes;
-
/tmp/SOURCE/D.l
é um link simbólico relativo para /tmp/SOURCE/B.d
;
-
/tmp/TARGET/
está vazio no momento.
A partir desse estado inicial, eu executo o tipo de comando mencionado no título deste post, o tipo de comando que eu quero "reverter" (como explicado abaixo):
$ rsync -L -a /tmp/SOURCE/C.d /tmp/SOURCE/D.l /tmp/TARGET
Depois que eu executar este comando, /tmp/TARGET/
ficará assim:
$ /usr/bin/tree -aF /tmp/TARGET/
/tmp/TARGET/
├── C.d/
│ ├── w
│ └── y
└── D.l/
└── z
Note em particular que, embora sob /tmp/SOURCE
e /tmp/TARGET
os caminhos relativos
C.d/w
C.d/y
D.l/z
existe, somente aqueles sob /tmp/TARGET
são caminhos "reais". Por um "caminho real" $P
, quero dizer que, grosso modo, a saída de readlink -f $P
é novamente $P
(ou, mais precisamente, ${P:a}
). Por exemplo,
$ readlink -f /tmp/TARGET/C.d/w
/tmp/TARGET/C.d/w
mas
$ readlink -f /tmp/SOURCE/C.d/w
/tmp/SOURCE/A.d/w
O problema
No contexto atual, o que quero dizer com "inverter" o comando rsync -L
anterior é basicamente copiar os arquivos regulares em /tmp/TARGET/
para seus originais em /tmp/SOURCE
, deixando o < em> estrutura de /tmp/SOURCE
inalterado.
Em particular, após essa "transferência reversa", os links simbólicos em /tmp/SOURCE
devem permanecer links simbólicos e devem apontar para exatamente os mesmos referentes que antes.
Estou procurando uma maneira de realizar tal "reversão" que seja comparável em complexidade / dificuldade ao comando rsync -aL
usado para realizar a transferência "para frente" em primeiro lugar.
Uma desvantagem deste exemplo simples é que é tão simples que alguém é tentado a resolver o problema com força bruta. Por exemplo,
$ rsync /tmp/TARGET/C.d/w /tmp/SOURCE/A.d
$ rsync /tmp/TARGET/C.d/y /tmp/SOURCE/A.d/x
$ rsync /tmp/TARGET/D.l/z /tmp/SOURCE/B.d
IOW, em uma situação tão simples, essa abordagem de força bruta não é muito mais difícil do que executar a transferência rsync -L
original. Em geral, no entanto, a estratégia de força bruta pode ser muito mais difícil de realizar, quando comparada à transferência original.
Este exemplo é simplificado demais porque os hosts de origem e de destino são os mesmos. Em geral, eles não serão, então evite soluções que dependam desse recurso do exemplo.
FWIW, o script a seguir cria a configuração do exemplo de brinquedo acima.
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/{A.d/{w,x},B.d/z}
ln -s ../A.d/w $BASEDIR/SOURCE/C.d/w
ln -s ../A.d/x $BASEDIR/SOURCE/C.d/y
ln -s B.d $BASEDIR/SOURCE/D.l