rsync
来自的标志的文档-L
:
-L, --copy-links 将符号链接转换为引用文件/目录
这个问题是关于如何“反转”最初使用rsync -L ...
.
对我来说,用一个简单的具体例子来解释“反向”的意思是最容易的。
设置
假设我有目录/tmp/SOURCE/
和/tmp/TARGET/
,如下所示:
$ /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/
特别要注意以下细节:
- 的内容
/tmp/SOURCE/C.d
是指向常规文件的相对符号链接/tmp/SOURCE/A.d
;- 符号链接
/tmp/SOURCE/C.d/w
及其引用的基本名称相同; /tmp/SOURCE/C.d/y
符号链接(即)的基本名称y
与其引用对象(即x
)的基本名称不同;
- 符号链接
/tmp/SOURCE/D.l
是一个相对符号链接/tmp/SOURCE/B.d
;/tmp/TARGET/
目前为空。
从这个初始状态,我运行本文标题中提到的命令,我想要“反转”的命令类型(如下文进一步解释):
$ rsync -L -a /tmp/SOURCE/C.d /tmp/SOURCE/D.l /tmp/TARGET
运行此命令后,/tmp/TARGET/
看起来像这样:
$ /usr/bin/tree -aF /tmp/TARGET/
/tmp/TARGET/
├── C.d/
│ ├── w
│ └── y
└── D.l/
└── z
特别注意的是,虽然在 Both/tmp/SOURCE
和/tmp/TARGET
相对路径下
C.d/w
C.d/y
D.l/z
存在,只有下面的/tmp/TARGET
才是“真实”路径。我所说的“真实路径”是$P
指,粗略地说, 的输出readlink -f $P
又是$P
(或者更准确地说,${P:a}
)。例如
$ readlink -f /tmp/TARGET/C.d/w
/tmp/TARGET/C.d/w
但
$ readlink -f /tmp/SOURCE/C.d/w
/tmp/SOURCE/A.d/w
问题
在当前上下文中,我所说的“反转”之前的rsync -L
命令基本上是将常规文件复制/tmp/TARGET/
到它们的原件下/tmp/SOURCE
,留下结构的/tmp/SOURCE
不变。
特别是,在此“反向传输”之后,下面的符号链接/tmp/SOURCE
应保持符号链接,并且应指向确切地与之前相同的指称。
我正在寻找一种方法来执行这种“反转”,其复杂性/难度与rsync -aL
首先用于执行“正向”传输的命令相当。
这个简单示例的一个缺点是很简单人们很想用暴力来解决问题。例如
$ 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,在如此简单的情况下,这种强力方法并不比运行原始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/{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
答案1
有一些选项允许 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
是否必要,但我会让你尝试一下。
答案2
我认为你不能直接在rsync
. --keep-dirlinks
( )选项-K
将使符号链接目录保持不变,但符号链接文件仍将被覆盖。
我能找到的最接近的解决方案是一个小 ( bash
) 脚本
( cd TARGET && find . -type f -print0 | sed 's!^./!!' ) |
while IFS= read -d $'\0' -r f
do
s=$(readlink -f SOURCE/"$f")
rsync -a TARGET/"$f" "${s:-f}"
done
这TARGET
一次将每个文件放入一个文件中,检查其中的符号链接目标SOURCE
并rsync
直接应用于该文件。