Linuxマージフォルダー:rsync?


13

フォルダーのコピーが2つあります

src/
dest/

以下を実行して、それらをマージします。

ファイルがのみにある場合、srcそれをに移動したいdest

ファイルがのみにある場合、destIEを放置したまま無視したいです。

ファイルが両方にあり、同じ内容(つまり、サイズと日付が同じ)の場合は、から削除しますsrc

ファイルが両方にあり、内容が同じでない場合は、ファイルsrcを手動でマージできるように残しておきます。

この最後のカテゴリに含まれるファイルはごく少数(合計ファイルの0%〜5%)でなければなりませんが、両方のファイルと同じファイルを両方のファイルから区別する方法はわかりませんが、異なります。

私はこれをどのように行うかを理解しようとしましrsyncたが、今のところ役に立ちません。

回答:


17

機能テストは限られているため、このコマンドには注意してください(--dry-run):

rsync -avPr --ignore-existing --remove-source-files src/ dest

末尾の/に注意してください。これはsrc自体をコピーする代わりにsrcに再帰するため、既存のパスを維持する必要があります。

--ignore-existingフラグを--remove-source-filesフラグと組み合わせて使用​​することにより、srcからdestに同期されたファイル、つまりdestにのみ存在していなかったファイルのみをsrcから削除します。

同期されていないファイル、つまり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コマンドの両方によって適切に処理されます。


修正:同じコマンドがdestに既に存在する場合、そのコマンドはsrcからファイルを削除しません
Tok

うん:(それは私が把握するのは難しい見つけることだという部分です。。
デビッド・オニール

2
さて、良いニュースは、それほど面倒なことなく独立して解決できることです:(for file in `find src/ -type f`; do diff $file `echo $file | sed 's/src/dest/'` && rm $file || echo $file; done必要に|| echo $file応じてスキップできます。完全
Tok

気の利いた:それは私が必要なものです。あなたの答えにそれを編集してください、そして私はそれを受け入れます!
デビッドオニール

@Tok:コマンドは、特殊文字(空白、、\?*[頭文字-)を含むファイル名で停止します。変数の置換を二重引用符で囲み、--ファイル名の前にユーティリティに渡す必要があります。find … -exec …代わりに、の出力を解析する代わりに使用しますfindrmミックスのコマンド、これは、災害のためのレシピです。
ジル「SO-悪であるのをやめる」

6

ユニゾンはあなたが探しているツールです。guiを好むならunison-gtkを試してください。しかし、私はそれが同様のファイルを削除するとは思わない:ユニゾンは両方のディレクトリを同一にしようとする。それでも、簡単に1)コピーするファイルを識別します。2)手動マージが必要なもの。


OPが求めるものを正確に実行するわけではありませんが、OPの究極の目標を達成しているようです。+1
ライアンC.トンプソン

+1残念ながら、これを実行しているサーバーにはユニゾンがインストールされておらず、インストールする権限もありません。しかし、これは他の誰かへの良い答えかもしれません。
デビッドオニール

1
unison実行可能ファイルはseas.upenn.edu/~bcpierce/unison//download/…からダウンロードできます。ホームディレクトリのどこかにインストールします。これは1つのファイルです。
-JooMing

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
  ' {} \;

別のアプローチは、たとえばfunionfsまたはunionfs-fuse使用して、あるディレクトリを別のディレクトリの上にユニオンマウントすることです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.