限られた機能テストしか実行していないため、このコマンド (--dry-run) には注意してください:
rsync -avPr --ignore-existing --remove-source-files src/ dest
末尾の / に注意してください。これは、src 自体をコピーするのではなく、src に再帰するためです。これにより、既存のパスが維持されます。
--ignore-existing フラグを --remove-source-files フラグと組み合わせて使用すると、src から dest に同期されたファイルのみを src から削除します。つまり、以前は dest にのみ存在しなかったファイルです。
同期されていないファイル、つまり src/ のように dest/ に既に存在するファイルを削除するには、次を使用できます:
for file in `find src/ -type f`; do diff $file `echo $file | sed 's/src/dest/'` && rm $file || echo $file; done
または
find src -type f -exec bash -c 'cmp -s "$0" "${0/#src/dest}" && rm "$0"' {} \;
ファイル名に空白/改行/…を含めることができる場合…特殊文字に関するGillesのコメントに関しては、これは確かに注意すべきことであり、多くの解決策がありますが、最も簡単なのは -i を rm に渡すことで、すべての削除の前にプロンプトが表示されます。ただし、src/ またはその親パスが検索用に提供されている場合、完全修飾パスにより、すべてのファイル名が引用符なしで diff コマンドと rm コマンドの両方によって適切に処理されるはずです。
ユニゾン あなたが探しているツールです。 GUI を使用したい場合は unison-gtk を試してください。ただし、同様のファイルが削除されるとは思いません。 unison は、両方のディレクトリを同一にしようとします。それにもかかわらず、簡単に 1) コピーするファイルを識別します。 2) 手動マージが必要なもの。
次のスクリプトは、適切に処理する必要があります。ファイルをソースから宛先に移動し、必要に応じてファイルを上書きしたり、ディレクトリを作成したりすることはありません。通常のファイルやディレクトリではないファイル (シンボリック リンクなど) と同様に、対応する別のファイルが宛先にあるソース ファイルはそのまま残ります。ソースに残っているファイルは、競合があるファイルです。注意してください、私はまったくテストしていません.
cd src
find . -exec sh -c '
set -- "/path/to/dest/$0"
if [ -d "$0" ]; then # the source is a directory
if ! [ -e "$1" ]; then
mv -- "$0" "$1" # move whole directory in one go
fi
elif ! [ -e "$0" ]; then # the source doesn't exist after all
: # might happen if a whole directory was moved
elif ! [ -e "$1" ]; then # the destination doesn't exist
mv -- "$0" "$1"
elif [ -f "$1" ] && cmp -s -- "$0" "$1"; then # identical files
rm -- "$0"
fi
' {} \;
もう 1 つの方法は、たとえば funionfs や unionfs-fuse を使用して、1 つのディレクトリを別のディレクトリの上にユニオン マウントすることです。