Linux: Bandingkan Struktur Direktori Tanpa Membandingkan File

55

Apa cara terbaik dan paling sederhana untuk membandingkan dua struktur direktori tanpa benar-benar membandingkan data dalam file? Ini berfungsi dengan baik:

diff -qr dir1 dir2_

Tapi itu sangat lambat karena membandingkan file juga. Apakah ada saklar untuk diff atau alat cli sederhana untuk melakukan ini?

Jonah
sumber
Dengan "struktur direktori", maksud Anda hanya jalur direktori, atau jalur file direktori dan non-direktori?
intuited
Ya, folder dan file.
Jonah
1
Dalam hal ini Anda harus menghapus -type dopsi dari jawaban @ slartibartfast, atau periksa jawaban saya.
intuited

Jawaban:

36

Berikut ini (jika Anda mengganti direktori pertama untuk direktori1 dan yang kedua untuk direktori2) harus melakukan apa yang Anda cari dan cepat:

find directory1 -type d -printf "%P\n" | sort > file1
find directory2 -type d -printf "%P\n" | sort | diff - file1

Prinsip dasarnya adalah bahwa ia mencetak semua direktori termasuk jalur subdirektori relatif terhadap direktori directoryN dasar.

Ini bisa jatuh (menghasilkan output aneh) jika Anda memiliki carriage return di beberapa nama direktori tetapi tidak yang lain.

Slartibartfast
sumber
Ini tidak baik bagi saya, karena jika satu direktori berisi folder dengan beberapa ribu file di dalamnya semuanya terdaftar secara individual, sementara diff -rqhanya menunjukkan direktori root ada di satu, dan melanjutkan.
Chris Jefferson
Seperti yang ditunjukkan (tahun lalu) oleh intuited, untuk menjawab pertanyaan OPs, -type d harus dihapus sehingga file dipertimbangkan dalam perbandingan serta direktori
user2746401
Saya mengerti dan menghargai pembacaan pernyataan masalah itu. Itu bukan bacaan saya saat itu. Apakah Anda merekomendasikan saya mengedit jawaban saya untuk menanggapi pertanyaan yang diperbarui? Saya baik-baik saja melakukan itu jika Anda pikir itu akan bermanfaat bagi beberapa orang, dan saya baik-baik saja meninggalkan solusi dan komentar mengatur jalan mereka sekarang, yang tampaknya cukup efektif.
Slartibartfast
34
vimdiff <(cd dir1; find . | sort) <(cd dir2; find . | sort)

akan memberi Anda tampilan sisi-sisi yang bagus dari dua hierarki direktori dengan setiap bagian umum dilipat.

garyjohn
sumber
Solusi ini gagal secara acak. Ketika vim membaca (atau membaca ulang) deskriptor file sementara, itu sudah hilang.
Denilson Sá Maia
23

Saya biasanya menggunakan rsyncuntuk tugas ini:

rsync -nav --delete DIR1/ DIR2

HATI - HATI SANGAT HATI untuk selalu menggunakan opsi-n, alias--dry-run, atau akan menyinkronkan (mengubah konten) direktori.

Ini akan membandingkan file berdasarkan waktu dan ukuran modifikasi file ... Saya pikir itulah yang benar-benar Anda inginkan, atau setidaknya Anda tidak keberatan jika melakukan itu? Saya merasa bahwa Anda hanya ingin itu terjadi lebih cepat , bukan karena Anda perlu mengabaikan perbedaan antara isi file. Jika Anda ingin tidak mencantumkan file yang berbeda dengan nama yang sama, saya pikir penambahan --ignore-existingopsi akan melakukannya.

Juga menyadari bahwa tidak menempatkan /pada akhir DIR1akan menyebabkan ia membandingkan direktori DIR1 dengan isi dari DIR2.

Hasil akhirnya sedikit bertele-tele, tetapi akan menunjukkan kepada Anda file / direktori mana yang berbeda. File / direktori yang ada DIR2dan tidak DIR1akan diawali dengan kata deleting.

Untuk beberapa situasi, jawaban @ slartibartfast mungkin lebih sesuai, meskipun Anda harus menghapus -type dopsi untuk mengaktifkan daftar file non-direktori. rsyncakan lebih cepat jika Anda punya banyak file / direktori untuk dibandingkan.

intuisi
sumber
Jawaban yang sangat bagus. Dalam output rsync sulit untuk melihat deleting...teks tetapi mungkin salah satu cara yang lebih baik untuk membandingkan file sambil tetap mempertahankan kecepatan. Jawaban lain di sini lebih cepat ketika membedakan file tidak diperlukan ... seperti pada contoh OP, tapi saya sangat suka yang ini.
Joel Mellon
Inilah yang saya cari. Saya memiliki beberapa file dengan ukuran yang berbeda dalam sepasang pohon direktori besar, dan saya ingin tahu yang mana. Ini mencapai tujuan itu hanya dalam hitungan detik.
suprjami
Mungkin ide yang baik untuk menjalankannya dengan pengguna yang memiliki akses hanya baca. Seperti sudo -u nobody rsync -nav --delete d1 d2asalkan bendera untuk 'orang lain' memungkinkan membaca.
user1182474
Saat menjalankan solusi ini saya mendapat "daftar file bangunan ... selesai \ n mengirim X byte yang diterima Y byte Z byte / detik ukuran totalnya adalah A speedup adalah B" (di mana saya mengganti XYZAB untuk angka). Apakah itu berarti semuanya identik? Karena tidak menyebutkan sesuatu yang lebih spesifik? Terima kasih sebelumnya
Scott H
Untuk menjawab pertanyaan saya sendiri, saya bereksperimen menambahkan file yang berbeda untuk masing-masing, dan tampaknya tidak ada file / dir tertentu yang disebutkan dalam output berarti semuanya sama.
Scott H
18

Mirip dengan jawaban ls tetapi jika Anda menginstal pohon maka Anda bisa

tree dir1 > out1
tree dir2 > out2
diff out1 out2
angka
sumber
7
Atau untuk menghindari tmpfiles,diff <( tree dir1 ) <( tree dir2 )
Joel Mellon
1
Saya merekomendasikan menjalankan pohon dengan ibendera, yang tidak mencetak garis-garis pohon ( tree -i dir1, dll). Jika struktur direktori berbeda di satu tempat, file lain yang cocok mungkin memiliki lebih banyak atau lebih sedikit |simbol dalam output pohon, dan diff akan menangkap garis-garis itu bahkan jika path file identik.
askewchan
2
diff <(tree -i dir1) <(tree -i dir2) sejauh ini merupakan jawaban terbaik. Saya tergoda untuk downvote semua jawaban yang menyarankan diff atau rsync sebagai pertanyaan yang secara eksplisit mengatakan TIDAK untuk membaca konten file. CATATAN: Saran untuk menggunakan dua pipa membutuhkan penggunaan spasi di antara tanda kurung, ikuti contohnya dengan tepat. Misalnya untuk membandingkan dua volume 20G setelah cadangan, jawaban pohon membutuhkan waktu sekitar 5 detik. Yang lain butuh 20+ menit.
Jason Morgan
3

Saya hanya mencari solusi untuk masalah ini. Solusi yang paling saya sukai adalah:

comm <(ls DIR1) <(ls DIR2)

Ini memberi Anda 3 kolom: 1 - file hanya di DIR1, 2 - file hanya di DIR2, 3 - file hanya di DIR3 Untuk lebih jelasnya lihat posting blog ini .

Kyrisu
sumber
Di mana DIR3ditentukan? Yang saya lihat adalah DIR1dan DIR2.
Michael Dorst
Saya mencobanya, dan (dari apa yang saya tahu) hasilnya adalah: semua file hanya di DIR1dalam kolom 1 , semua file hanya di DIR2dalam kolom 2 , dan semua file dibagi oleh keduanya di kolom 3 . Itu semacam berguna, tetapi apakah Anda tahu bagaimana orang dapat menghapus kolom 3 dan hanya meninggalkan perbedaan? Saya memiliki banyak file untuk disortir, dan sebagian besar identik. Saya tidak perlu melihat apa yang sama.
Michael Dorst
1
Juga, saya menemukan bahwa comm <(ls DIR1) <(ls DIR2)itu tidak bekerja secara rekursif. Untuk itu saya gunakan comm <(ls -R1 DIR1) <(ls -R1 DIR2). ls -Rmerangkak melalui direktori secara rekursif, dan ls -1(perhatikan bahwa itu adalah satu , bukan L ) membuat lscetak hanya satu nama file per baris.
Michael Dorst
@Michael: comm -3(lihat man comm).
Zaz
2
ls > dir1.txt

ls > dir2.txt

Kemudian cukup bedakan kedua daftar itu.

MDMarra
sumber
Sepertinya OP menginginkan pusaka jalur. Ini akan membedakan semua file di direktori saat ini. Masih bisa diperdebatkan, tetapi mungkin, bahwa dia hanya menginginkan direktori; dia mungkin menginginkan nama file daripada isi file.
intuited
@intuited - Anda benar. Saya salah baca.
MDMarra
2

Ini adalah solusi optimal

diff --brief -r dir1 dir2

--brief switch melaporkan hanya apakah file berbeda, bukan detail perbedaannya.

jkshah
sumber
1
OP sudah ada -qdi pertanyaan, yang merupakan alias untuk --brief. Jawaban ini tidak memberikan informasi baru.
Michael Dorst
1
OP tidak ingin perbandingan konten file. But it's really slow because it's comparing files too.
Joel Mellon
1

gunakan "diff -qr" untuk mendapatkan file yang berbeda dan kemudian saring perbandingan file dengan grep agar hanya mendapatkan nama file yang hanya ada di salah satu direktori.

diff -qr dir1 dir2 | grep -v "Files.*differ" 
Anonim, tanpa nama
sumber
1

Ini berfungsi untuk kebutuhan spesifik saya untuk menemukan file yang hilang di pohon diharapkan cocok

diff <( cd dir1; find * |sort ) <(cd dir2; find * | sort)
amhest
sumber
-3

Saya pikir hanya rsync yang userfull. Mengapa?

diff hanya berguna untuk struktur yang menyimpan file dan direktori. Diff tidak memberikan kode keluar yang memadai saat kami menggunakan symlink. Dalam situasi itu, diff dapat mengembalikan 2 kode keluar, bahkan jika src dan dst identik (waktu, ukuran, nama, cap waktu, menunjuk softlink, dll).

dir, filesystem tidak menjamin pemesanan file, bahkan jika isi direktori pada src dan dst identik. Mungkin Anda harus memfilter output ls dengan mengurutkannya. Tapi pure ls hanya menampilkan nama simpul.

mungkin skrip termasuk diff, cmp, test -X untuk tipe node akan berguna, tetapi ingat tentang kelebihan yang dibuat oleh banyak test / cmp berjalan. Script akan sangat lambat.

Seperti biasa, jika Anda ingin mendapatkan info sederhana "dirs is / not identik", Anda harus menggunakan rsync dengan opsi -n (kering). Jika Anda ingin menemukan apa yang berbeda, gunakan perintah diff.

Znik
sumber
Saya ingin tahu mengapa minus?
Znik