Bagaimana cara menyalin-menggabungkan dua direktori?

112

Saya memiliki dua direktori gambar dan gambar2 dengan struktur ini di Linux:

/images/ad  
/images/fe  
/images/foo  

... dan 4000 folder lainnya

dan yang lainnya seperti:

/images2/ad  
/images2/fe  
/images2/foo

... dan 4000 folder lainnya

Masing-masing folder ini berisi gambar dan nama direktori di bawah gambar dan gambar2 persis sama, namun isinya berbeda. Lalu saya ingin tahu bagaimana saya bisa menyalin-menggabungkan gambar / images2 / iklan menjadi gambar / iklan, gambar / images2 / foo menjadi gambar / foo dan seterusnya dengan semua 4000 folder ..

ssierral
sumber
1
Apakah file akhir dinamai sama di kedua direktori?
Simply_Me
Tidak ... misalnya dalam gambar / iklan adalah 1.jpg, 2.jpg dan 3.jpg. Tetapi di images2 / iklan adalah 4.jpg dan 5.jpg
ssierral
4
@AmirAliAkbari, saya tidak berpikir itu duplikat - pertanyaan lain pada dasarnya adalah 'Apakah saya melakukan penggabungan?' (jawab: tidak). Pertanyaan ini adalah tentang cara menggabungkan 2 hierarki direktori.
maxschlepzig

Jawaban:

173

Ini adalah pekerjaan untuk rsync . Tidak ada manfaatnya melakukan ini secara manual dengan loop shell kecuali jika Anda ingin memindahkan file daripada menyalinnya.

rsync -a /path/to/source/ /path/to/destination

Dalam kasus Anda:

rsync -a /images2/ /images/

(Catatan trailing slash on images2, kalau tidak itu akan menyalin /images/images2.)

Jika gambar dengan nama yang sama ada di kedua direktori, perintah di atas akan menimpa /images/SOMEPATH/SOMEFILEdengan /images2/SOMEPATH/SOMEFILE. Jika Anda ingin mengganti hanya file yang lebih lama, tambahkan opsi -u. Jika Anda ingin selalu menyimpan versi /images, tambahkan opsi --ignore-existing.

Jika Anda ingin memindahkan file dari /images2, dengan rsync, Anda dapat meneruskan opsi --remove-source-files. Kemudian rsync menyalin semua file secara bergantian, dan menghapus setiap file setelah selesai. Ini jauh lebih lambat daripada bergerak jika direktori sumber dan tujuan berada pada sistem file yang sama.

Gilles
sumber
14
..add -P jika Anda ingin melihat kemajuan ..
Meetai.com
1
Saya akan menambahkan bahwa tidak ada manfaat untuk menggunakan shell lingkaran rumit sini bahkan jika Anda tidak ingin memindahkan mereka bukannya menyalin mereka-dalam kasus itu hanya menggunakan rsync, maka rm -r /images.
Wildcard
1
Saya juga ingin menunjukkan bahwa penting untuk menyertakan garis miring untuk setiap direktori . Sebagai contoh, jika Anda hanya berlari rsync -a images images2, itu hanya akan menyalin gambar2 ke dalam gambar daripada menggabungkannya.
Kyle Challis
1
@ s3cur3 Oh. Dari 2 ke (implisit) 1. Itu tidak intuitif. Terima kasih, saya memperbaiki jawaban saya.
Gilles
1
@MaxCoplan No. Rsync bukan alat interaktif.
Gilles
43

Pilihan terbaik, seperti yang sudah diposting, tentu saja rsync. Namun demikian juga serempak akan menjadi perangkat lunak yang hebat untuk melakukan pekerjaan ini. Keduanya dapat digunakan di beberapa sistem operasi.

Rsync

rsync menyinkronkan dalam satu arah dari sumber ke tujuan. Demikian pernyataan berikut ini

rsync -avh --progress Source Destination

menyinkronkan semuanya dari Sumber ke Tujuan . Folder gabungan berada di Tujuan .

-a berarti "mengarsipkan" dan menyalin segala sesuatu secara rekursif dari sumber ke tujuan menjaga hampir segalanya.

-v memberikan lebih banyak output ("verbose").

-h untuk dibaca manusia.

--kemajuan untuk menunjukkan berapa banyak pekerjaan yang dilakukan.

Jika Anda ingin hanya memperbarui yang tujuan folder dengan yang lebih baru file dari folder sumber:

rsync -avhu --progress source destination

Serentak

serentak menyinkronkan di kedua arah. Demikian pernyataan berikut ini

unison Source Destination

menyinkronkan kedua direktori di kedua arah dan akhirnya sumber sama dengan tujuan. Ini seperti melakukan rsync dua kali dari sumber ke dest dan sebaliknya.

Untuk penggunaan lebih lanjut, lihat halaman manual atau situs web berikut:

  1. https://www.cis.upenn.edu/~bcpierce/unison/
  2. https://rsync.samba.org/
debiarch
sumber
2
Saya ingin menyebutkan bahwa jalur yang benar ke folder harus dengan garis miring di akhir rsync -avh --progress source/ destination/, jika tidak folder sumber akan dibuat di folder tujuan, setidaknya dalam kasus saya yang seperti ini.
electroid
Ini berfungsi baik untuk saya (dengan garis miring di folder). Terima kasih!
Leopoldo Sanczyk
5
for dir in images2/*; do mv "$dir"/* "images/$(basename "$dir")"; done

Lingkari semua konten images2menggunakan glob yang diperluas (untuk menghindari masalah dengan penguraian ls) kemudian mvisi item tersebut ke entri yang cocok images. Penggunaan basenameuntuk melepaskan yang memimpin images2dari jalur bola.

Etan Reisner
sumber
tolong tambahkan rincian lebih lanjut tentang apa yang perintah Anda lakukan sehingga berguna untuk pembaca di masa depan juga :)
Ramesh
1

@ inulinux12, Anda dapat menggunakan satu baris forloop berikut dari baris perintah:

$ for dir in images2/*; do mv "$dir"/* "${dir/2/}"; done

Ini akan memindahkan semua file dari images2ke imagesdalam direktori masing-masing. Catatan: ini mengasumsikan tidak ada file dengan nama yang sama.

Sebagai contoh:

Sebelum eksekusi:

$ ls -R images*
images:
ad  adfoo  fe
images/ad:
jpg.1  jpg.2
images/adfoo:
jpg.7
images/fe:
jpg.5
images2:
ad  adfoo  fe
images2/ad:
jpg.3
images2/adfoo:
jpg.6
images2/fe:
jpg.4

Setelah eksekusi:

$ ls -R images*
images:
ad  adfoo  fe
images/ad:
jpg.1  jpg.2  jpg.3
images/adfoo:
jpg.6  jpg.7
images/fe:
jpg.4  jpg.5
Simply_Me
sumber
3
Jangan parsing output dari ls. mywiki.wooledge.org/ParsingLs
Etan Reisner
@EtanReisner Terima kasih atas sarannya; tampaknya skenario yang cukup sempit meskipun diberi informasi yang diberikan dalam pertanyaan.
Simply_Me
2
@Simply_Me Meskipun benar bahwa biasanya akan baik-baik saja, Anda benar-benar tidak ingin itu meledak ketika Anda menekan sebuah kasus yang tidak Anda andalkan. Ini dapat menyebabkan masalah yang sangat buruk. Belum lagi itu cukup sering (seperti dalam kasus ini) hampir sepele diganti dengan gumpalan sederhana. Lihat jawaban saya sebagai contoh.
Etan Reisner
@Simply_Me Skenario termasuk nama file dengan spasi, yang cukup umum untuk gambar.
Gilles
@Gilles dan @Etan Reisner, terima kasih atas masukannya, saya menghargainya! Memperbarui dan menguji jawaban saya untuk menggunakan substitusi string, dan hasilnya menjadi lebih cepat daripada menggunakan basenamedalam situasi khusus ini (tidak perlu meminta basenameini). Sekali lagi terima kasih atas komentar yang membangun.
Simply_Me