2つのディレクトリをコピーマージする方法は?


112

Linuxには、この構造を持つ2つのディレクトリimagesとimages2があります。

/images/ad  
/images/fe  
/images/foo  

...およびその他の4000フォルダー

そして、他のようなものです:

/images2/ad  
/images2/fe  
/images2/foo

...およびその他の4000フォルダー

これらの各フォルダには画像が含まれ、imagesおよびimages2の下のディレクトリ名はまったく同じですが、内容は異なります。次に、4000個すべてのフォルダーで、/ images2 / adの画像をimages / adにコピー/マージし、/ images2 / fooの画像をimages / fooにコピーする方法を知りたいと思います。


1
両方のディレクトリで同じ名前の終了ファイルがありますか?
Simply_Me 14

いいえ。たとえば、images / adの場合、1.jpg、2.jpg、3.jpgです。しかし、images2 / adには4.jpgと5.jpg
sierral

4
@AmirAliAkbari、私はそれが重複しているとは思わない-他の質問は基本的に「mvはマージを行うのか?」(答え:いいえ)。この質問は、2つのディレクトリ階層をマージする方法に関するものです。
maxschlepzig

回答:


173

これはrsyncの仕事です。ファイルをコピーするのではなく移動する場合を除き、シェルループを使用して手動でこれを行うメリットはありません。

rsync -a /path/to/source/ /path/to/destination

あなたの場合:

rsync -a /images2/ /images/

(末尾のスラッシュに注意してくださいimages2、そうでない場合はにコピーされ/images/images2ます。)

同じ名前の画像が両方のディレクトリに存在する場合、上記のコマンドはで上書きさ/images/SOMEPATH/SOMEFILE/images2/SOMEPATH/SOMEFILEます。古いファイルのみを置き換える場合は、オプションを追加します-u。バージョンを常に保持する場合は/images、オプションを追加します--ignore-existing

/images2rsyncを使用してからファイルを移動する場合は、オプションを渡すことができます--remove-source-files。次に、rsyncはすべてのファイルを順番にコピーし、完了したら各ファイルを削除します。これは、ソースディレクトリと宛先ディレクトリが同じファイルシステム上にある場合、移動するよりもはるかに遅くなります。


14
..進捗状況を確認したい場合は-Pを追加します。
Meetai.com

1
ここでトリッキーなシェルループを使用しても、コピーではなく移動したい場合に利点はありません。その場合はrsync、を使用しますrm -r /images
ワイルドカード

1
また、各ディレクトリの末尾のスラッシュを含めることが重要であることも指摘したいと思います。たとえば、単にranを実行した場合rsync -a images images2、それらをマージするのではなく、単にimages2を画像にコピーします。
カイルチャリス

1
@ s3cur3ああ。2から(暗黙)1まで。これは直感的ではありません。おかげで、答えを修正しました。
ジル

1
@MaxCoplanいいえ。Rsyncは対話型ツールではありません。
ジル

43

すでに投稿されているように、最良の選択はもちろんrsyncです。それにも関わらず、ユニゾンはこの仕事をするための素晴らしいソフトウェアになるでしょう。両方ともいくつかのオペレーティングシステムで使用できます。

Rsync

rsyncは、ソースから宛先への一方向で同期します。したがって、次のステートメント

rsync -avh --progress Source Destination

SourceからDestinationまでのすべてを同期します。マージされたフォルダーはDestinationにあります。

-aは「アーカイブ」を意味し、ソースからデスティネーションにすべてを再帰的にコピーし、ほぼすべてを保持します。

-vは、より多くの出力を提供します(「詳細」)。

-hは人間が読める形式です。

-どのくらいの作業が行われたかを示す進行

ソースフォルダーの新しいファイルで宛先フォルダーのみを更新する場合:

rsync -avhu --progress source destination

ユニゾン

ユニゾンは両方向に同期します。したがって、次のステートメント

unison Source Destination

両方のディレクトリを両方向に同期し、最終的にソースが宛先に等しくなります。これは、ソースからデスティネーションへ、またはその逆にrsyncを2回実行するようなものです。

より高度な使用法については、manページまたは次のWebサイトを参照してください。

  1. https://www.cis.upenn.edu/~bcpierce/unison/
  2. https://rsync.samba.org/

2
フォルダーへの正しいパスは末尾にスラッシュが付いている必要がありますrsync -avh --progress source/ destination/。そうでない場合、少なくともこのような場合、ソースフォルダーは宛先フォルダーに作成されます。
electroid

これは私にとってはうまくいきます(フォルダー内の末尾にスラッシュが付いています)。ありがとうございました!
レオポルドサンチク16年

5
for dir in images2/*; do mv "$dir"/* "images/$(basename "$dir")"; done

すべての内容をループimages2展開グロブを使用して(解析の問題を回避するためls)、その後mvに一致するエントリに対するこれらの項目の内容images。グロブされたパスからbasename先頭を削除するために使用しimages2ます。


将来の読者にも役立つように、コマンドの動作に関する詳細を追加してください:)
Ramesh 14

1

@ inulinux12では、forコマンドラインから次の1行のループを使用できます。

$ for dir in images2/*; do mv "$dir"/* "${dir/2/}"; done

これはからのすべてのファイルを移動しますimages2imagesそれぞれのディレクトリに。注:これは、同じ名前のファイルがないことを前提としています。

例えば:

実行前:

$ ls -R images*
images:
ad  adfoo  fe
images/ad:
jpg.1  jpg.2
images/adfoo:
jpg.7
images/fe:
jpg.5
images2:
ad  adfoo  fe
images2/ad:
jpg.3
images2/adfoo:
jpg.6
images2/fe:
jpg.4

実行後:

$ ls -R images*
images:
ad  adfoo  fe
images/ad:
jpg.1  jpg.2  jpg.3
images/adfoo:
jpg.6  jpg.7
images/fe:
jpg.4  jpg.5

3
の出力を解析しないでくださいlsmywiki.wooledge.org/ParsingLs-イータン
Reisner

@EtanReisner提案をありがとう。質問で与えられた情報を考えると、かなり狭いシナリオのようです。
Simply_Me 14

2
@Simply_Me通常は問題ないことは事実ですが、期待していなかったケースを見つけたときに爆発することは望ましくありません。それは本当に悪い問題を引き起こす可能性があります。言うまでもなく、それは非常に頻繁に(この場合のように)単純なglobでほぼ自明に置き換え可能です。その例として私の答えをご覧ください。
エタンReisner

@Simply_Meシナリオには、スペースを含むファイル名が含まれますが、これは画像ではかなり一般的です。
ジル

@Gillesと@Etan Reisner、入力をありがとう、私は感謝します!文字列置換を使用するように私の回答を更新およびテストしbasename、この特定の状況で使用するよりも高速になるようになりました(basenameこれを呼び出す必要はありません)。建設的なコメントをありがとう。
Simply_Me 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.