it-swarm-id.com

Bagaimana cara menimpa file target dengan mv?

Saya punya banyak file dan direktori dalam subdirektori yang ingin saya pindahkan ke direktori induk. Sudah ada beberapa file dan direktori di direktori target yang perlu ditimpa. File yang hanya ada di target harus dibiarkan tidak tersentuh. Bisakah saya memaksa mv untuk melakukan itu? Itu (mv * ..) mengeluh

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

Apa yang saya lewatkan?

175
EricSchaefer

Anda harus menyalinnya ke tujuan dan kemudian menghapus sumbernya, menggunakan perintah cp -r * .. diikuti oleh rm -rf *.

Saya rasa Anda tidak dapat "menggabungkan" direktori menggunakan mv.

128
dogbane

rsync mungkin akan menjadi pilihan yang lebih baik di sini. Sesederhana rsync -a subdir/ ./.

Pohon tes saya dalam format filename: contents:

./file1:root
./file2:root
./dir/file3:dir
./dir/file4:dir
./subdir/dir/file3:subdir
./subdir/file1:subdir

Menjalankan rsync:

$ rsync -a -v subdir/ ./
sending incremental file list
./
file1
dir/
dir/file3

Memberi:

./file1:subdir
./file2:root
./dir/file3:subdir
./dir/file4:dir
./subdir/dir/file3:subdir
./subdir/file1:subdir

Dan kemudian, untuk meniru mv, Anda mungkin ingin menghapus direktori sumber:

$ rm -r subdir/

Memberi:

./file1:subdir
./file2:parent
./dir/file3:subdir
./dir/file4:dir

Jika ini salah, bisakah Anda memberikan contoh serupa (mis. Menggunakan pohon pengujian saya dari dekat bagian atas jawaban ini) dengan hasil yang diinginkan?

77
Mikel

rsync dapat menghapus sumber setelah salinan dengan --remove-source-files parameter. Ini harus menjadi cara yang nyaman untuk melakukan apa yang Anda inginkan.

Dari rsync man page:

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

Anda dapat melakukan ini dengan cp dan rm, tetapi tanpa menyalin sejumlah besar data Anda (mungkin) berusaha menghindari transfer. @mattdm menyinggung ini di komentarnya , dan jawaban untuk pertanyaan lain memiliki diskusi yang lebih lengkap tentang berbagai opsi.

cp -rlf source destination
rm -r source

Intinya, -l pilihan untuk perintah cp membuat tautan keras ke file daripada menyalin datanya ke file baru.

24
palswim

Berikut ini skrip yang memindahkan file dari bawah /path/to/source/root ke jalur yang sesuai di bawah /path/to/destination/root.

  • Jika direktori ada di sumber dan tujuan, konten dipindahkan dan digabung secara rekursif.
  • Jika file atau direktori ada di sumber tetapi tidak di tujuan, itu dipindahkan.
  • File atau direktori apa pun yang sudah ada di tujuan tertinggal. (Secara khusus direktori yang digabungkan ditinggalkan di sumbernya. Ini tidak mudah untuk diperbaiki.)

Hati-hati, kode yang belum diuji.

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
' {} \;

Utas ini sudah ada selama bertahun-tahun dan masih menempati peringkat # 1 di google jadi saya ingin menambahkan metode lain. Bagaimana saya biasanya melakukan ini: mengemas konten subdir ke dalam tarball, memindahkan tarball ke direktori induk dan kemudian mengekstraknya dengan perilaku default --overwrite. Ini tepat seperti yang Anda cari. Setelah itu, Anda dapat menghapus subdir.

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

Jika Anda memiliki cukup penyimpanan, Anda dapat melakukannya dengan cara berikut:

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

Pastikan tidak ada file penting dengan tanda ~ di bagian akhir, tetapi jika ada, Anda dapat menambahkan --suffix=whateveryouwant bukannya default.

0
4D3H2