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
/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
ファイルに直接適用されます。