回答:
mv
ディレクトリをマージまたは上書きすることはできません--force
。オプションを使用している場合でも、メッセージ「mv: 'a'を 'b'に移動できません:ディレクトリが空ではありません」で失敗します。
あなたは他のツール(のように使用してこの問題を回避することができrsync
、find
またはさえcp
)を、しかし、あなたは慎重に検討してくださいする必要があります。
rsync
(理想的と別のものに1つのディレクトリの内容をマージすることができます--remove-source-files
1つの安全に正常に転送されたもののみソースファイルを削除するオプション、および通常の許可/所有/時間の保存オプションを使用して-a
必要であれば)rsync
の--link-dest=DIR
オプションを組み合わせて(可能な場合、ファイルの内容をコピーする代わりにハードリンクを作成する)--remove-source-files
、通常のmv
。--link-dest
ためには、ソースディレクトリへの絶対パス(または宛先からソースへの相対パス)を指定する必要があります。--link-dest
意図しない方法で使用され(複雑化の原因となる可能性はありません)、ソースへの絶対パスを(または決定して)知る必要があり--link-dest
、再び空のディレクトリ構造を残してクリーンアップしますあたり1。find
して、ターゲットでソースディレクトリ構造を順番に再作成し、実際のファイルを個別に移動することができますcp
ハードリンクを作成することができますマージと非常に類似した結果を作成します(同じ既存のファイルに簡単に言えば、追加のポインタ)、 mv
(およびポインタのみが作成されているので非常にIO-効率的で、実際のデータをコピーする必要がありません)これらの回避策(存在する場合)のどれが適切かは、特定のユースケースに大きく依存します。
いつものように、これらのコマンドを実行する前に考えて、バックアップを作成してください。
1:rsync --remove-source-files
ディレクトリは削除されないことに注意してください。そのためfind -depth -type d -empty -delete
、空のソースディレクトリツリーを削除するために、後ほど何かをする必要があります。
mv
のDebianで使用される実装を-重点が上であることを試みた、manページがこの動作を言及していないので、...
--delete
ファイルのみを削除することに注意してください。
-H
関数を使用してハードリンクを保持することも、宛先を使用してファイルをハードリンクすることもできます--link-dest
。ただし、使用する前にマニュアルページを参照してください。
rsync -av /source/ /destination/
(after checking)
rm -rf /source/
--remove-source-files
正常に転送されたファイルのみを削除するという利点があるfind
ため、空のディレクトリを削除するために使用でき、rsync
出力を確認せずに転送されなかったすべてのものが残されます。
cpコマンドの-l
オプションを使用すると、完全なデータコピーの代わりに同じファイルシステムにファイルのハードリンクを作成できます。次のコマンドは、フォルダーを親フォルダー()にコピーします。親フォルダーには、という名前のディレクトリが既に含まれています。source/folder
destination
folder
cp -rl source/folder destination
rm -r source/folder
必要に応じて、-P
(--no-dereference
-シンボリックリンクを逆参照しない)または-a
(--archive
-すべてのメタデータを保持し、-P
オプションも含む)を使用することもできます。
cp
いうよりrsync
、すべてのシステムが持っているのでcp
、誰もがそれに精通しています。
cp
の操作時間でのマージ機能を取得しmv
ます。
-n
mv /fs1/file /fs2/
(ファイルシステム全体)コピーを実行してから削除します。
mv
「ターゲットディレクトリがまだ存在しない場合」は動作しますが、「効率的に」またはあなたがそれを呼ぶものでcp -rl
なくても失敗します。
次の4つの手順をお勧めします。
cd ${SOURCE};
find . -type d -exec mkdir -p ${DEST}/\{} \;
find . -type f -exec mv \{} ${DEST}/\{} \;
find . -type d -empty -delete
さらに良いことに、次のようなセマンティクスを実装するスクリプトがありますmv
。
#!/bin/bash
DEST="${@:${#@}}"
ABS_DEST="$(cd "$(dirname "$DEST")"; pwd)/$(basename "$DEST")"
for SRC in ${@:1:$((${#@} -1))}; do (
cd "$SRC";
find . -type d -exec mkdir -p "${ABS_DEST}"/\{} \;
find . -type f -exec mv \{} "${ABS_DEST}"/\{} \;
find . -type d -empty -delete
) done
rsync -u
新しいmv
バージョンの場合にのみ)同等の処理を行いたい場合は、(少なくとも一部のバージョンでは)-u
オプションを使用することもできます。ただし、その場合は、ソースツリー内のファイルが新しくない場合に対応するために、空ではないソースディレクトリだけでなくソースディレクトリも削除する必要があります。@schuess:必要な場合、複数のSOURCE引数が存在するようです。
以下はディレクトリをマージする方法です。ファイルをコピーしてから削除するのではなく、ファイルの名前を変更するだけなので、rsyncよりもはるかに高速です。
cd source; find -type f -print0 | xargs -0 -n 1 -I {} mv '{}' 'dest/{}'
dest
がin と同じ名前のディレクトリである場合、コマンドは失敗しsource
ます。そして、ファイルはに移動さdest
れsource
ます。コマンドは、mv source/* source/dest/.
最も純粋なコピーには、tar(-)Bブロック読み取りコピー方式を使用します。
たとえば、ソースパス内から(必要に応じて「cd」):
tar cBf - <sourcefolder> | (cd /your/target/folder ; tar xBf -)
これにより、ソースツリーの正確なコピーが作成され、所有者とアクセス許可はそのままになります。ターゲットフォルダーが存在する場合、データはマージされます。既に存在するファイルのみが上書きされます。
例:
$ cd /data1/home
$ tar cBf - jdoe | (cd /data2/home ; tar xBf -)
コピーアクションが成功したら、ソース(rm -rf <source>
)を削除できます。もちろん、これは正確な動きではありません。ソースを削除するまで、データはコピーされます。
オプションとして、-vを使用して、冗長にすることができます(コピーされるファイルを画面に表示します)。 tar cBvf -
c
:作成B
:ブロック全体の読み取り(パイプ読み取りの場合)v
:詳細f
:書き込むファイルx
:抽出-
:stdout / stdinsourcefolder
することもできる*
(現在のフォルダに何のために)
f -
通常、tarの指定は不要です。デフォルトでは、stdin / writeからstdoutに読み取ります。
ここに私のために働いたスクリプトがあります。私はrsyncよりもmvを好むので、JewelとJonathan Mayerのソリューションを使用します。
#!/bin/bash
# usage source1 .. sourceN dest
length=$(($#-1))
sources=${@:1:$length}
DEST=$(readlink -f ${!#})
for SRC in $sources; do
pushd $SRC;
find . -type d -exec mkdir -p ${DEST}/{} \;
find . -type f -exec mv {} ${DEST}/{} \;
find . -type d -empty -delete
popd
done
cpやrsyncなどのコマンドを使用することはお勧めできません。大きなファイルの場合、時間がかかります。mvは、ファイルを物理的にコピーせずにiノードのみを更新するため、はるかに高速です。より良いオプションは、オペレーティングシステムのファイルマネージャを使用することです。OpenSuseには、Konquererというファイルマネージャーがあります。実際にコピーせずにファイルを移動できます。Windowsのような「カットアンドペースト」機能があります。ディレクトリAのすべてのサブディレクトリを選択します。右クリックして、同じ名前のサブディレクトリを含むディレクトリBに「移動」します。それらをマージします。同じ名前のファイルを上書きするか名前を変更するかを選択するオプションもあります。
mv
は使用時に何が起こるかを尋ねます。
Pythonソリューション
満足できる既存のソリューションを見つけることができなかったので、それを達成するために簡単なPythonスクリプトを作成することにしました。
特に、このメソッドはボトムアップでソースファイルツリーをたどるだけなので、効率的です。
また、ファイルの上書き処理などを好みに合わせてすばやく調整できます。
使用法:
move-merge-dirs src/ dest/
のすべてのコンテンツをsrc/*
に移動しdest/
、src/
消えます。
move-merge-dirs
#!/usr/bin/env python3
import argparse
import os
def move_merge_dirs(source_root, dest_root):
for path, dirs, files in os.walk(source_root, topdown=False):
dest_dir = os.path.join(
dest_root,
os.path.relpath(path, source_root)
)
if not os.path.exists(dest_dir):
os.makedirs(dest_dir)
for filename in files:
os.rename(
os.path.join(path, filename),
os.path.join(dest_dir, filename)
)
for dirname in dirs:
os.rmdir(os.path.join(path, dirname))
os.rmdir(source_root)
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description='Move merge src/* into dest. Overwrite existing files.'
)
parser.add_argument('src_dir')
parser.add_argument('dest_dir')
args = parser.parse_args()
move_merge_dirs(args.src_dir, args.dest_dir)
参照:https : //stackoverflow.com/questions/22588225/how-do-you-merge-two-directories-or-move-with-replace-from-the-windows-command
これは、ファイルとフォルダーを他の宛先に移動するためのコマンドです。
$ mv /source/path/folder /target/destination/
注意:mv
フォルダーがb̲e̲i̲n̲g m̲e̲r̲ge̲d̲(つまり、同じ名前の別のフォルダーが既に宛先に存在する)およびd̲e̲s̲t̲i̲n̲a̲t̲i̲o̲n̲ o̲n̲e̲ i̲s̲ n̲o̲t̲ e̲m̲pt̲yの場合、コマンドは機能しません。
mv:「/ source / path / folder」を「/ target / destination / folder」に移動できません:ディレクトリが空ではありません
宛先フォルダーが空の場合、上記のコマンドは正常に機能します。
したがって、いずれの場合でも両方のフォルダーをマージ
するには、2つのコマンドでそれを実行します。
$ cp -rf /source/path/folder /target/destination/
$ rm -rf /source/path/folder
または、両方を1回限りのコマンドとして組み合わせます。
$ cp -rf /source/path/folder /target/destination/ && rm -rf /source/path/folder
mv =移動
cp =コピー
rm =削除-r for directory(folder)
-f force execution
mv
。この答えは、より広い真実があればより良いでしょう。Linux、BSD、および「実際の」Unix、またはPOSIXまたはSUSからの参照。