再帰的な移動( `mv -rn`、例: `cp -rn`)、存在しないファイルのみを移動する

再帰的な移動( `mv -rn`、例: `cp -rn`)、存在しないファイルのみを移動する

コンテキスト

バックアップする必要があるユーザーアップロードコンテンツがあります。コンテンツは3つの別々のサーバー/var/www/domain/media/(各サーバーに一緒に配置)でホストされています。バックアップはNFS RAIDにマウントされます/var/www/domain/bak/

media/他のユーザーに属するのとは異なり、デフォルトではbak/Webアプリケーションは書き込みは可能ですmedia/が、読み取りのみbak/可能です。ユーザーは、アップロードしたコンテンツがGMT 00:00にバックアップされるまでのみ削除できます。

これは2つの問題を引き起こします。ユーザーが同じファイル名でバックアップ内のファイルを強制的に上書きでき、ファイルが2つの異なるmedia/サーバーに存在する可能性があります(ユーザーが別のサーバーから2回アップロードする場合)。

すべて4x CenOS 7(Web X 3 + Backup X 1)で実行されます。 「Web」サーバーはディスク容量が限られているため、ディスクがいっぱいになるのを防ぐために、コンテンツをバックアップサーバーに移動する必要があります。

持つ競争条件なししたがって、これは私たちが心配する必要はありません。バックアップは、ssh他の3台のマシンで順番にコマンドを実行することで、単一のバックアップマシンで実行されます。


現在のソリューション

バックアップするファイルの「移動」は、重複エントリを削除した後に実行されます。

find /var/www/domain/media/ -type f | > media
find /var/www/domain/bak/ -type f | awk '{a=gensub("bak","media",1); print a}' > bak
cat bak media | sort | uniq -d > dupes
cat dupes | xargs rm
cp -r /var/www/domain/media/* /var/www/domain/bak/
rm -rf /var/www/domain/media/*

これを使用する際の問題は、各ユーザーがサブディレクトリを持っていることmvです/var/www/domain/media/。たとえば、

media/user13/myvideo.webm
media/user13/walk-in-the-park.webm
media/user16/cat-video.webm
media/user17/presentation-may-2016.webm

bak/user13/mountai-trip.webm
bak/user13/walk-in-the-park.webm
bak/user14/reax-the-dog.webm

このコマンドはuser16およびuser17上書きを防ぐ必要がありますbak/user13/walk-in-the-park.webm


現在のソリューションの問題

media/重複を排除する代わりに維持したいと思います。別の場所にコピーしても同じ問題が発生します。これは日中に新しいファイルが表示され、コピーをそのコピーと同期させる必要があるためです。

すでに存在するファイルを削除せずにディレクトリ構造を維持しながら、media/存在しないファイルをすべて移動する方法は何ですか?bak/

つまり、次の作業を探しています。

source      | destination         | action
----------- | ------------------- | ----------------------------------
file exists | file does not exist | move (`mv`), source -> destination
file exists | file exists         | do nothing, both files stay as they are
no file     | file exists         | do nothing (will not trigger)
no file     | file does not exist | do nothing (well, there's nothing to do something with!)

よりエレガントなソリューションをお試しください

rsync私たちはこれを行うことができると思います。わかりましたが、--remove-source-files方法が見つかりません。いいえタイムスタンプ、チェックサム、ファイルサイズなどを確認してください。

チェックサムを完全に別々のプロセスとして保存して確認します。

ファイル名にのみ興味があります。これはファイルが破損する可能性があることを知っていますが、RAIDサーバーではなく通常のディスクに破損したファイルをインポートする方がはるかに簡単です。

rsync非ソリューションを歓迎します。shell移動を実行するスクリプトを作成したいと思います。現在のソリューション部分)。しかし、これがどれほど簡単に間違っている可能性があるのか​​考えてから放棄しました。

私も次のことを試しました。

tar -cf /var/www/domain/media | (cd /var/www/domain/bar; tar -kxf -)

ただし、メディアファイル(かなり大きい場合があります)の場合、速度が遅すぎてすべてのファイルを保持しますmedia/(ディスク容量が制限されています)。

答え1

ファイルがターゲットツリーにすでに存在する場合(メタデータに関係なく)、操作が実行されない場合は、--ignore-existingこのオプションをrsyncに渡します。

rsync -a --remove-source-files --ignore-existing /var/www/domain/media/ /var/www/domain/bak/

完全性を期すために、ソースとターゲットが同じファイルシステム上にある状況に基づいたソリューションがあります(この場合、findファイルを単にファイルシステムに移動するのではなく、ファイルをコピーして削除するので良いソリューションではありません)。ターゲットディレクトリ)。mvrsync

cd /var/www/domain/media
find -type f -exec '
  for x; do
    if ! [ -e "/var/www/domain/bak/$x" ]; then
      mkdir -p "/var/www/domain/bak/${x%/*}" &&
      mv -- "$x" "/var/www/domain/bak/$x"
    fi
  done
' sh {} +

関連情報