web-dev-qa-db-ja.com

ターゲットファイルをmvで上書きする方法は?

親ディレクトリに移動したいサブディレクトリに大量のファイルとディレクトリがあります。上書きする必要のあるファイルとディレクトリがすでにターゲットディレクトリにあります。ターゲットにのみ存在するファイルは変更しないでください。 mvにそれを強制することはできますか?それ (mv * ..)文句を言う

mv: cannot move `xyz' to `../xyz': Directory not empty

何が欠けていますか?

175
EricSchaefer

コマンドcp -r * ..に続けてrm -rf *を使用して、それらを宛先にコピーしてからソースを削除する必要があります。

mvを使用してディレクトリを「マージ」できるとは思いません。

128
dogbane

rsyncはおそらくここでより良いオプションです。 rsync -a subdir/ ./と同じくらい簡単です。

filenamecontents形式のテストツリー:

./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

これが間違っている場合、希望する結果を提供する同様の例(この回答の上部近くにある私のテストツリーを使用するなど)を提供できますか?

77
Mikel

rsyncは、コピー後に--remove-source-filesパラメータを使用してソースを削除できます。これは、希望どおりの操作を行うための便利な方法です。

rsync man pageから:

        --remove-source-files   sender removes synchronized files (non-dir)
52
Mike Chen

cprmを使用してこれを行うことができますが、(おそらく)転送を回避しようとしている大量のデータをコピーする必要はありません。 @mattdmは 彼のコメント でこれに言及しました、そして 別の質問に対する回答 はさまざまなオプションについてより完全な議論を持っています。

cp -rlf source destination
rm -r source

基本的に、cpコマンドの-lオプションは、データを新しいファイルにコピーするのではなく、ファイルへのハードリンクを作成します。

24
palswim

以下は、/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
' {} \;

このスレッドは何年にもわたって存在し、まだGoogleで1位にランクされているので、別のメソッドを追加したいと思いました。通常、これを行う方法:サブディレクトリのコンテンツを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
3
Simon Kraus

十分なストレージがある場合は、次の方法でそれを行うことができます。

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を追加できます。

0
4D3H2