「変更された場合にコピー」操作を実行するにはどうすればよいですか?


34

一連のファイルをディレクトリAからディレクトリBにコピーしたいのですが、ディレクトリAのファイルがディレクトリBのファイルと同一である場合、そのファイルはコピーしないでください(したがって、その変更時間は更新しました)。独自のスクリプトを作成せずに、既存のツールでそれを行う方法はありますか?

ユースケースを少し詳しく説明します:私は.c一時ディレクトリに多数のファイルを自動生成します(すべてのファイルを無条件に生成する必要がある方法によって)。そして、それらを再生成するときに、コピーしたいだけです実際のソースディレクトリに変更されたものは、変更されていないものを(古い作成時間で)makeそのままにしておくため、再コンパイルする必要はありません。(.cただし、生成されるファイルのすべてがファイルではないため、テキスト比較ではなくバイナリ比較を行う必要があります。)

(注:これは、https://stackoverflow.com/questions/8981552/speeding-up-file-comparions-with-cmp-on-cygwin/8981762#8981762で尋ねた質問から生まれましたこの操作を実行するために使用していたスクリプトファイルを高速化するために、特にシェルでこれを行う簡単な方法からスクリプトはcmpファイルのすべてのペアで何かを呼び出しますが、これらのプロセスをすべて開始するには時間がかかりすぎます。)


1
を使用diff -qr dirA dirBしてdirA、およびdirBに固有のファイルをそれぞれ確認できます。

1
@ brooks-mosesこれは本当にccacheに適した仕事です!
aculich

3
一意のファイルを表示する場合はdiffを使用できますが、変更されたものだけを表示する場合は@hesseを使用するrsync -avncか、long wayを使用しますrsync --archive --verbose --dry-run --checksum
aculich

回答:


29

rsyncはおそらくこれに最適なツールです。このコマンドには多くのオプションがありますので、manページを読んでください。--checksumオプションまたは--ignore-timesが必要だと思います


私はすでにそれを試しましたが、成功しなかったことに注意する必要がありました。これらのオプションは両方とも、rsyncがコピーを行うかどうかにのみ影響しますが、コピーを行わない場合でも、ターゲットファイルの変更時刻をソースと同じ時刻(-tオプションが指定されている場合)または同期時刻に更新します(-t指定されていない場合)。
ブルックスモーゼス

4
@Brooks Moses:ありません。少なくとも私のバージョンはrsyncそうではありません。私がこれを行うと:mkdir src dest; echo a>src/a; rsync -c src/* dest; sleep 5; touch src/a; rsync -c src/* deststat dest/aそのmtimeとctimeがのものより5秒古いことを示しますsrc/a
アンガス

@angus:なるほど。さて、あなたは正しい。鍵があると思われる--checksumオプション、およびもののlinux.die.net/man/1/rsyncは全く含まれていない、何もそれがどんな変更日が更新されたかどうかに影響を与えるを持っていることを暗示する、それにもかかわらず残される先の変更日を引き起こしそのまま。(一方で、この--ignore-timesオプションにはこの効果はありません。これにより、変更日は更新されます。)これは完全に文書化されていないように思えますが、これに頼ることはできますか?
ブルックスモーゼ

2
@BrooksMoses:信頼できると思います:rsyncのワークフローは次のとおりです。1)ファイルを更新する必要があるかどうかを確認します。2)その場合、ファイルを更新します。--checksumオプションは、それが更新されてはならない、そう言うのrsync)ステップ2に進んではいけません。
-enzotib

2
@BrooksMoses:--ignore-timeswithout --checksumはすべてのファイルをコピーするため、ファイルが同一であってもタイムスタンプを更新します。
enzotib

13

次のように-uスイッチを使用できますcp

$ cp -u [source] [destination]

manページから:

   -u, --update
       copy only when the SOURCE file is newer than the destination file or 
       when the destination file is missing

4
こんにちは、サイトへようこそ。ここでは、回答がもう少し充実していると期待しています。たとえば、-uフラグが何をするのか、どのように機能するのか、これがOPにどのように役立つのかの説明を含めることができます。ただし、この特定の場合、OPが新しい場合は同一のファイルをコピーし、タイムスタンプを変更するため、OPは回避しません。
テルドン

1
既に削除された同様のAのコメントから:「ソースのタイムスタンプが新しい場合(OP要求に対して宛先のタイムスタンプを更新する場合)、同じファイルもコピーするため、これは機能しません。」
slm

質問にはまったく答えませんが、それでも有用だと思います。
user31389

7

使用することrsync --checksumは「変更された場合にコピーする」ための一般的な方法ですが、特定の場合にはさらに良い解決策があります!

不必要にファイルを再コンパイルしたくない場合は、まさにこの目的のために構築されたccacheを使用する必要があります!実際、自動生成されたファイルの不必要な再コンパイルを回避するだけでなく、実行するたびに速度を上げmake clean、ゼロから再コンパイルします。

次に、「安全ですか?」と尋ねるでしょう。ええ、はい、ウェブサイトが指摘しているように:

安全ですか?

はい。コンパイラキャッシュの最も重要な側面は、実際のコンパイラが生成するのとまったく同じ出力を常に生成することです。これには、実際のコンパイラを使用した場合に生成されるものとまったく同じオブジェクトファイルとまったく同じコンパイラ警告が含まれます。ccacheを使用していることを確認できる唯一の方法は、速度です。

また、makefile の行にプレフィックスとして追加するだけで簡単に使用CC=できます(またはシンボリックリンクを使用できますが、makefileの方法の方がおそらく優れています)。


1
私は当初、誤解し、生成の一部を行うためにccacheを使用することを提案していると思っていましたが、今では理解しています-単にすべてのファイルをコピーし、ビルドプロセスでccacheを使用することで、変更されていませんでした。それは良いアイデアですが、私の場合はうまくいきません-私は何百ものファイルを持っていますが、通常は一度に1つまたは2つしか変更せず、Cygwinの下で実行されています。ファイルには数分かかります。それにもかかわらず、それはほとんどの人にとって良い答えだから支持されました!
ブルックスモーゼス

いいえ、すべてのファイルをコピーすることはお勧めしませんでした。代わりに、インプレースで.cファイルを自動生成できます(コピー手順を削除して、直接書き込みます)。そして、ccacheを使用します。何百ものccacheプロセスを開始することの意味がわかりません。これはgccの軽量ラッパーであり、プロジェクトの他の部分の再構築も高速化します。使ってみましたか?copy-methodとccacheの使用のタイミングを比較したいと思います。実際、2つの方法を組み合わせて、両方の利点を得ることができます。
-aculich

1
そうですね、コピーについては理解できました。明確に言うと、これは次のとおりです。ファイルを所定の場所に生成する場合、ccache file.c -o file.o数百のfile.cファイルがあるため、数百回呼び出すか、同等の処理を行う必要があります。私がそれをしていたときではcmpなくccache、それは数分かかりました-そしてcmp軽量ccacheです。問題は、Cygwinでは、プロセス開始するのに、まったく些細なプロセスであっても、無視できない時間を要することです。
ブルックスモーゼス

1
データポイントとして、for f in src/*; do /bin/true.exe; done30秒かかります。とにかく、私はWindowsベースのエディターを好みます。この種のタイミングの問題は別として、Cygwinは、ビルドサーバーにアップロードしない場合にローカルでテストするための軽量な場所として、ワークフローで非常にうまく機能します。同じOSでシェルとエディターを使用すると便利です。:)
ブルックスモーゼス

1
Windowsベースのエディターを使用する場合、Guest Additionsをインストールすれば共有フォルダーを使用して簡単に実行できます... このような奇妙なフープを飛び越えなければならないのは残念です...そして、一般的にコンパイルはVMでも高速になります。
aculich

3

これはあなたが必要なことをするはずです

diff -qr ./x ./y | awk '{print $2}' | xargs -n1 -J% cp % ./y/

どこで:

  • xは、更新/新しいフォルダーです
  • yはコピー先です
  • awkはdiffコマンドから各行の2番目の引数を取ります(スペースのあるファイル名には追加のものが必要になるかもしれません-今は試せません)
  • xargs -J%は、cpの適切な場所にファイル名を挿入します

1
-1これは非常に複雑で、移植性-Jがなく(bsd固有であり、GNU xargsでは-I)、同じファイルのセットが両方の場所に既に存在しない場合は正しく動作しないためです(touch x/boogrepが提供する場合Only in ./x: booパイプラインでエラーが発生します)。など、ジョブ用に構築されたツールを使用しますrsync --checksum
-aculich

さらに良いことに、この特定のケースではccacheを使用します。
aculich

1、私は同様のタスクに使用することに破ることができることはよく知られているコマンドのセットは、(差分を取るためにここに来た)、まだrsyncをよりよく、この特定のタスクのための可能性があるため
NTG

3

複数のマスターをサポートし、すでにsshキーとvpnを別々にセットアップしているため、ユニゾンを使用するのが好きです。rsync

したがって、1つのホストのみのcrontabで、15分ごとに同期させました。

* / 15 * * * * [-z "$(pidof unison)"] &&(タイムアウト25m unison -sortbysize -ui text -batch -times / home / master ssh://192.168.1.12//home/master -path dev -logfile /tmp/sync.master.dev.log)&> /tmp/sync.master.dev.log

その後、どちらの側でも開発でき、変更が伝播します。実際、重要なプロジェクトでは、同じツリーをミラーリングする最大4台のサーバーがあります(3台は、cronから一斉に実行され、そうでないものを指します)。実際、LinuxとCygwinのホストは混在していますが、cygwin環境外のwin32のソフトリンクの感覚は期待できません。

このルートを使用する場合、のない空の側に最初のミラーを作成します-batch。つまり、

unison -ui text  -times /home/master ssh://192.168.1.12//home/master -path dev

もちろん、バックアップファイル、アーカイブなどを無視する設定があります。

 ~/.unison/default.prf :
# Unison preferences file
ignore = Name {,.}*{.sh~}
ignore = Name {,.}*{.rb~}
ignore = Name {,.}*{.bak}
ignore = Name {,.}*{.tmp}
ignore = Name {,.}*{.txt~}
ignore = Name {,.}*{.pl~}
ignore = Name {.unison.}*
ignore = Name {,.}*{.zip}

    # Use this command for displaying diffs
    diff = diff -y -W 79 --suppress-common-lines

    ignore = Name *~
    ignore = Name .*~
    ignore = Path */pilot/backup/Archive_*
    ignore = Name *.o

私はそれを見ましたが、unison「ファイルの最終更新日を更新しない」ことを意味するオプションを見つけることができませんでした。あるの?それ以外の場合、これはまったく異なる問題に対する素晴らしい答えです。
ブルックスモーゼス

1
-timesそれは私のために。Unisonにはドライランモードもあります。
マルコス

まあ、設定times=false(または中止-times)がそれを行います。以前にドキュメントでそれを見逃した方法がわかりません。ありがとう!
ブルックスモーゼス

喜んでお手伝いします。modtime、パーミッション、ソフトリンクなどの保存に関しては、私はこだわりです。しばしば見落とされる
マルコス

1

一方でrsync --checksum正解、このオプションは互換性がありませんので注意があり--times、それが--archive含まれ--times、あなたがしたいそうならば、rsync -a --checksumあなたは本当にする必要がありrsync -a --no-times --checksum


「互換性がない」とはどういう意味ですか?
ov

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