web-dev-qa-db-ja.com

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

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

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

(メモとして:これは私が尋ねた質問から生まれました https://stackoverflow.com/questions/8981552/speeding-up-file-comparions-with-cmp-on-cygwin/8981762#8981762 、この操作を実行するために使用していたスクリプトファイルを高速化しようとしていましたが、これを行うには、独自のスクリプトを作成するよりも優れた方法があるかどうかを本当に質問する必要があります。シェルスクリプトでこれを行う方法では、ファイルのすべてのペアでcmpのようなものが呼び出され、それらすべてのプロセスの開始には時間がかかります。)

37
Brooks Moses

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

31
Adam Terrey

-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
19
gu1

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

不必要にファイルを再コンパイルしないようにするには、この目的のために作成された ccache を使用する必要があります。実際、自動生成されたファイルの不必要な再コンパイルを回避するだけでなく、make cleanを実行して最初から再コンパイルするたびにスピードアップします。

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

安全ですか?

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

そして、それは 使いやすい メイクファイルのCC=行に接頭辞として追加するだけです(またはシンボリックリンクを使用できますが、メイクファイルの方法がおそらくより優れています)。

7
aculich

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

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

どこ:

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

私はnisonを使用してrsyncを優先して使用します。これは、複数のマスターをサポートし、sshキーとVPNを個別に設定しているためです。

したがって、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からunisonを実行し、そうでないサーバーを指します)。実際、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
3
Marcos

rsync --checksumが正解ですが、このオプションは--timesと互換性がなく、--archiveには--timesが含まれるため、rsync -a --checksumを使用する場合は、本当にrsync -a --no-times --checksumが必要です。

1
Vladimir Kornea