
共通の要素が多数ある2つのディレクトリツリーをマージしようとしていますが、各ディレクトリツリーには2つのツリーの1つにのみ存在する要素があります。私が経験している主な問題は、mv
同じ相対パスを持つ2つのサブディレクトリに遭遇したときにソース(with -f
)またはターゲット(with -n
)を維持しますが、2つのサブディレクトリセットの組み合わせを取得できないことです。 。もちろんrsync
withを使用することもできますが、--remove-source-files
それを行うと、実際の移動ではなく実際にデータをコピーしてから古いファイルを削除します。どちらのディレクトリツリーにも数百ギガバイトのデータが含まれており、どちらも同じパーティションにあるので、時間を節約するために可能であれば実際の移動を実行したいと思います。
これで、find * -type file -exec mv -n {} /destination/{}
ターゲットディレクトリがすでに存在する場合にのみソースからターゲットにファイルを移動します。コマンドの前にこのような接頭辞を付けることができますが、mv -n * /destination/
そうすると、最上位ディレクトリのみが表示されます。一行にする方法はありますか?ファイルをコピーする前にディレクトリが存在することを確認するスクリプトをいつでも作成できますが、これは基本的な操作のように見え、より簡単な方法が必要です。
答え1
警告:この回答は、ハードリンク(FATなど)をサポートしていないファイルシステムには適用されません。
別のオプション(携帯性が高い)は次のとおりです。
CDソースディレクトリ 探す。 -type f -print0 | cpio --pass-through --null --link --make-directories宛先ディレクトリ
cpio
(コピーイン&アウト)は初期恐竜ですtar
。同様に、tar
アーカイブを作成したり、アーカイブから抽出したりできます。 (私が間違っている場合は修正してください)とは異なり、tar
単一のコマンドを使用してディレクトリツリーをコピーできます。 (私の考えでは、あなたがこれを行うことができるようです。)これがまさにその意味です。 「ファイル名が null で区切られると予想されます」を意味します。つまり、出力を読み取ります。これは、「可能であれば、ソースディレクトリのファイルをターゲットディレクトリにリンクします」を意味します。説明は必要ありません。tar -cf - source option(s) and arguments(s) | tar -xf - destination option(s) and arguments(s)
--pass-through
--null
find … -print0
--link
--make-directories
これは省略できます。必要に応じて、またはを追加してください。cpio –p0ld dest_dir
--verbose
-v
さて、これがすべて終わった後、
- 競合を確認し、適切に対処してください。
- ターゲットディレクトリがハードリンクでいっぱいになっていることを確認してください。
- ソースディレクトリを削除します。
答え2
prename
あなたが望むものを得るためにそれを使用することができます。一部のディストリビューション(Debian / Ubuntuなど)では、デフォルトでインストールされ、エイリアスを指定する必要がありますrename
。他のディストリビューションでは異なるディストリビューションを使用できますrename
。ソースディレクトリの上のディレクトリに変更することで、次のことができます。
find source -exec prename 's:^source:/path/to/dest:' {} +
これにより、ターゲットツリーにすでに存在するファイルの移動が拒否され、ディレクトリ名が重複している場合は後で削除できるように空のディレクトリが残されます。既存のファイルを上書きする-f
オプションを追加できます。prename
例:
$ mkdir -p dir1/{common,sub1} dir2/{common,sub2}
$ touch dir1/sub1/file dir2/sub2/file dir1/common/common dir2/common/common dir1/common/diff1 dir2/common/diff2
$ tree dir*
dir1
├── common
│ ├── common
│ └── diff1
└── sub1
└── file
dir2
├── common
│ ├── common
│ └── diff2
└── sub2
└── file
4 directories, 6 files
$ find dir2 -depth -exec rename 's/^dir2/dir1/' {} +
Can't rename dir2/sub2/file dir1/sub2/file: No such file or directory
dir2/common/common not renamed: dir1/common/common already exists
dir2/common not renamed: dir1/common already exists
dir2 not renamed: dir1 already exists
$ tree dir*
dir1
├── common
│ ├── common
│ ├── diff1
│ └── diff2
├── sub1
│ └── file
└── sub2
└── file
dir2
└── common
└── common
4 directories, 6 files
修正する:
与えられたソースには通常、prename
(したがって「p」)がバンドルされています。perl
Debian / Ubuntuではpackageの一部ですperl
。自分で解決したい場合は、この質問に対する回答者の一人が -組み込みの名前変更の代わりにPerlの名前変更ユーティリティを入手する別のリポジトリを作成しました。https://github.com/subogero/rename
答え3
rsync
以下を使用してファイルをコピーするのではなく、実際にファイルを移動できます。
rsync -av --link-dest "$PWD"/src/ --remove-source-files src/ dst
一般的な方法では、rsync -av --remove-source-files src/ dst
ファイルがからからコピーされ、src/
ソースdst
が削除されます。このオプションを追加し--link-dest
てディレクトリをポイントすると、ターゲットファイルsrc/
はコピーされずにリンクされます。
私が見ることができる唯一の警告は次のとおりです。
--link-dest
ターゲットディレクトリに相対的であるため、フルパスを指定する必要があります。src/
rsync
ファイルがリンクされると、ファイルがコピーされたと報告されないため、出力はファイルがコピーされなかったことを報告rsync -av --progress
します。
気づく利用可能なディスク容量の90%を消費したファイルでテストされました。コピーは失敗しますが(90%+ 90%>> 100%)、接続/移動は正しく機能します。