親ディレクトリに移動したいサブディレクトリに大量のファイルとディレクトリがあります。ターゲットディレクトリには、上書きする必要のあるファイルとディレクトリが既にあります。ターゲットにのみ存在するファイルは変更しないでください。それを強制mv
することはできますか?それ(mv * ..
)文句を言う
mv: cannot move `xyz' to `../xyz': Directory not empty
私は何が欠けていますか?
mv -f
正解ではないのだろうか。
親ディレクトリに移動したいサブディレクトリに大量のファイルとディレクトリがあります。ターゲットディレクトリには、上書きする必要のあるファイルとディレクトリが既にあります。ターゲットにのみ存在するファイルは変更しないでください。それを強制mv
することはできますか?それ(mv * ..
)文句を言う
mv: cannot move `xyz' to `../xyz': Directory not empty
私は何が欠けていますか?
mv -f
正解ではないのだろうか。
回答:
あなたは、コマンド使用して、先にコピーして、ソースを削除する必要がありますcp -r * ..
が続きをrm -rf *
。
を使用してディレクトリを「マージ」できるとは思わないmv
。
mv
同じファイルシステムを使用しているため、おそらく高速ですか?cp -l
実際にファイルを移動するのではなく、ハードリンクの作成に使用するとどうなりますか?
cp -a
代わりに使用する必要がcp -r
あります。
cp -rl source destination && rm -r source
。
rsync
ここでおそらくより良いオプションでしょう。と同じくらい簡単rsync -a subdir/ ./
です。
私のテストツリーfilename
::contents
形式:
./file1:root
./file2:root
./dir/file3:dir
./dir/file4:dir
./subdir/dir/file3:subdir
./subdir/file1:subdir
実行中rsync
:
$ rsync -a -v subdir/ ./
sending incremental file list
./
file1
dir/
dir/file3
与える:
./file1:subdir
./file2:root
./dir/file3:subdir
./dir/file4:dir
./subdir/dir/file3:subdir
./subdir/file1:subdir
次に、エミュレートするにはmv
、おそらくソースディレクトリを削除する必要があります。
$ rm -r subdir/
与える:
./file1:subdir
./file2:parent
./dir/file3:subdir
./dir/file4:dir
これが間違っている場合、希望する結果を備えた同様の例を提供できますか(たとえば、この回答の上部近くからテストツリーを使用して)。
rm -r
最後に追加して基本的に同じにしましたmv
。
mv
アトミックで、inode番号を保持するため(ファイルを開いたままにすることができます)、コピーを作成するのに時間とスペースを必要としません。
cp -r; rm -r
です。その意味で、rsync
言及する価値があると思います。
rsync
--remove-source-files
パラメータを使用してコピー後にソースを削除できます。これは、あなたが望むことをする便利な方法であるはずです。
からrsync man page
:
--remove-source-files sender removes synchronized files (non-dir)
cp -r; rm
空き容量がないため使用できませんでした。代わりにrsync --remove-source-files
、使用済みのディスク領域を最小限に抑えたため、まったく同じファイルをコピーすることを避けました。
cp
and rm
でこれを行うことができますが、大量のデータをコピーすることなく、(おそらく)転送を避けようとしています。@mattdmは彼のコメントでこれをほのめかし、別の質問への回答にはさまざまなオプションに関するより完全な議論があります。
cp -rlf source destination
rm -r source
基本的に、コマンドの-l
オプションは、cp
データを新しいファイルにコピーするのではなく、ファイルへのハードリンクを作成します。
cp -al source destination
ます。所有者の情報と権限を保持するために変更しました。
cp
デフォルトで上書きします。この-f
オプションは、rm
新しくコピーしようとする前にファイルを削除しようとします(これは、プロセスが書き込み用にファイルを開けない場合に役立ちますが、代わりにエラーが発生したことを確認したい人もいます)。OPにとって重要かどうかはわかりませんが、-f
とにかく答えにフラグを追加しました。
以下に、ファイルを下/path/to/source/root
から対応するパスに移動するスクリプトを示します/path/to/destination/root
。
未テストのコードに注意してください。
export dest='/path/to/destination/root'
cd /path/to/source/root
find . -type d \( -exec sh -c '[ -d "$dest/$0" ]' \; -o \
-exec sh -c 'mv "$0" "$dest/$0"' {} \; -prune \) \
-o -exec sh -c '
if ! [ -e "$dest/$0" ]; then
mv -f "$0" "$dest/$0"
fi
' {} \;
\;
前-o
の最初の行にfind
コマンドを、そしてあなたが脱出はならない!
でif
-それだけだ!
、ではない\!
このスレッドは何年もそこにあり、まだグーグルで1位にランクされているので、別のメソッドを追加したいと思いました。通常の方法:subdirコンテンツをtarballにパックし、tarballを親ディレクトリに移動してから、デフォルトの--overwrite動作で抽出します。これはまさにあなたが探しているものです。その後、サブディレクトリを削除できます。
cd xyz
tar -cvzpf tmp.tar.gz *
mv tmp.tar.gz ../tmp.tar.gz
cd ..
tar -xvzpf tmp.tar.gz
rm -rf xyz
rm -f tmp.tar.gz
十分なストレージがある場合は、次の方法で実行できます。
mv -bfv directory_1/* directory_2/ # all duplicate source files/directories
# will have ~ appended to them
find -name "*~" -delete # will recursively find and delete all files
# with ~ on the end
末尾に〜が付いている重要なファイルがないことを確認しますが、ある場合--suffix=whateveryouwant
はデフォルトの代わりに追加できます。
mv -f
か?