Diberikan dua pohon direktori, bagaimana saya bisa mengetahui file mana yang berbeda menurut konten?

786

Jika saya ingin menemukan perbedaan antara dua pohon direktori, saya biasanya hanya menjalankan:

diff -r dir1/ dir2/

Ini menghasilkan persis apa perbedaan antara file yang sesuai. Saya tertarik hanya mendapatkan daftar file yang sesuai yang isinya berbeda. Saya berasumsi bahwa ini hanyalah masalah meneruskan opsi baris perintah diff, tetapi saya tidak dapat menemukan apa pun di halaman manual.

Ada saran?

Mansoor Siddiqui
sumber
1
Sehubungan dengan salah satu direktori, bagaimana cara mendapatkan hanya file / direktori yang ekstra di yang lain?
Sandeepan Nath
gunakan dircmpperintah pada unix (bukan linux)
roblogic

Jawaban:

1119

Anda mengatakan Linux, jadi Anda beruntung (setidaknya itu harus tersedia, tidak yakin kapan ditambahkan):

diff --brief --recursive dir1/ dir2/ # GNU long options
diff -qr dir1/ dir2/ # common short options

Sebaiknya lakukan apa yang Anda butuhkan.

Jika Anda juga ingin melihat perbedaan untuk file yang mungkin tidak ada di direktori mana pun:

diff --brief --recursive --new-file dir1/ dir2/ # GNU long options
diff -qrN dir1/ dir2/ # common short options
Mark Loeser
sumber
12
Bagus. Tapi lebih pendek diff -qr dir1/ dir2/dan versi saya diperpanjang untukdiff -qr dir1/ dir2/ | grep ' differ'
sobi3ch
1
@skv mengapa? Ini perintah yang sama dengan jawaban. Saya hanya mengubah --briefpintasannya saja -q.
sobi3ch
2
@skv Tidak persis apa yang ditanyakan pertanyaan asli, tetapi memperbarui jawaban untuk mengakomodasi pertanyaan ini juga.
Mark Loeser
3
@ MikeMaxwell Harus --brief. -briefdiartikan sebagai -b -r -i -e -f, dengan kata lain sebagai satu set bendera bukan sebagai opsi tunggal.
Daboross
2
@daboross: wow, saya telah menggunakan Unix / Linux selama ini, dan saya tidak pernah menyadari ada perbedaan antara '-' dan '-'. (Saya tidak berpikir '-' ada ketika saya mulai.) Terima kasih atas penjelasannya!
Mike Maxwell
287

Perintah yang saya gunakan adalah:

diff -qr dir1/ dir2/

Persis sama dengan Markus :) Tapi jawabannya mengganggu saya karena menggunakan berbagai jenis bendera, dan itu membuat saya terlihat dua kali. Menggunakan lebih banyak tanda verbose dari Mark akan menjadi:

diff  --brief --recursive dir1/ dir2/

Saya minta maaf karena memposting ketika jawaban lain benar-benar dapat diterima. Tidak bisa menahan diri ... berusaha untuk tidak terlalu menyombongkan diri.

FPC
sumber
3
sangat menghargai konsistensi - tetapi jangan merasa buruk; Saya telah mengangkat jawaban Markus juga;)
Gerard ONeill
10
..jadi masuk akal untuk menaruh jawaban yang berbeda dengan rasa yang berbeda? IMHO tidak! Apakah masuk akal jika saya menggabungkan kedua jawaban ke satu jawaban yang konsisten? Iya! ;)
sobi3ch
1
Hanya sebuah pertanyaan; apa artinya qberdiri? Apakah ini singkatan dari sesuatu? Saya tidak dapat menemukan logika di balik q..
kramer65
3
@ kramer65 - sama dengan "--brief", tapi saya kira Anda bertanya-tanya mengapa q? Mungkin untuk cepat? "-b" diambil dengan "abaikan perubahan jumlah ruang putih" menurut halaman manual.
FPC
4
@ kramer65 Saya percaya qitu untuk quiet, umumnya berarti kurang bertele-tele.
Gogeta70
105

Saya suka menggunakan git diff --no-index dir1/ dir2/, karena itu dapat menunjukkan perbedaan warna (jika Anda memiliki opsi yang diatur dalam konfigurasi git Anda) dan karena itu menunjukkan semua perbedaan dalam output paging panjang menggunakan "kurang".

Alan Porter
sumber
25
Rapi. Siapa yang akan menduga bahwa git dapat mengubah direktori arbitrer, bukan hanya repo terhadap file-nya?
Dan Dascalescu
2
Colordiff skrip Perl sangat berguna di sini, dapat digunakan dengan svn dan normal diff.
Felipe Alvarez
4
Jika Anda membandingkan (seperti saya) 2 dir sebagai proyek git terpisah / repo maka Anda perlu menambahkan --no-indexlebih banyak di stackoverflow.com/a/1792477/473390 . Saya sudah memperbarui jawaban alan-porter.
sobi3ch
Saya suka yang ini, saya juga menemukan bahwa jika Anda menambahkan --name-status ke baris perintah, itu hanya akan menampilkan daftar nama file dengan bendera "M / A / D" untuk status Dimodifikasi / Ditambahkan / Dihapus.
gzh
Itu terjadi sehingga kedua direktori sebenarnya mengandung folder .git, bagaimana saya bisa mengecualikannya dari perbandingan?
Muhamed Cicak
35

Kedua perintah ini pada dasarnya melakukan hal yang diminta:

diff --brief --recursive --no-dereference --new-file --no-ignore-file-name-case /dir1 /dir2 > dirdiff_1.txt

rsync --recursive --delete --links --checksum --verbose --dry-run /dir1/ /dir2/ > dirdiff_2.txt

Pilihan di antara mereka tergantung pada lokasi dir1 dan dir2:

Ketika direktori berada pada dua drive yang terpisah, diff mengungguli rsync. Tetapi ketika dua direktori yang dibandingkan berada di drive yang sama, rsync lebih cepat. Itu karena diff menempatkan beban yang hampir sama pada kedua direktori secara paralel, memaksimalkan beban pada kedua drive.

rsync menghitung checksum dalam potongan besar sebelum benar-benar membandingkannya. Itu mengelompokkan operasi i / o dalam potongan besar dan mengarah ke pemrosesan yang lebih efisien ketika semuanya terjadi pada satu drive.

CodeBug
sumber
3
rsync tidak hanya lebih cepat untuk file pada drive tunggal, tetapi juga memungkinkan untuk membandingkan file dalam subdirs, misalnya rsync --options /usr /bin /var /sbin /lib /old_rootsecara efektif akan membandingkan root saat ini /(dengan menentukan semua subdirs di dalamnya) dan /old_root(berisi misalnya beberapa cadangan yang lebih tua /), yang merupakan sesuatu yang diff -rdapat bisa. Dan jika Anda menganggap bahwa file dengan ukuran, izin, dan cap waktu yang sama mungkin belum berubah, meninggalkannya --checksumakan memberi Anda kecepatan yang sangat tinggi (jika tidak sampai selesai) memeriksa file mana yang mungkin telah berubah.
Matija Nalis
1
Apa tujuan dari --deletedengan rsync?
Tom Hale
2
Tujuan --delete adalah untuk menghapus file yang ada di tujuan-dir yang tidak (lagi) hadir di dir-sumber
Thomas Munk
2
Dalam hal ini (dengan --dry-runbenderanya) tidak ada yang benar-benar dihapus, rsynchanya mencetak file mana yang dalam dir1 tetapi tidak dalam dir2
mata
11
Saya akan merekomendasikan mengutamakan --dry-runselalu agar tidak sengaja melupakannya.
Dave Rager
22

Meld juga merupakan alat yang hebat untuk membandingkan dua direktori:

meld dir1/ dir2/

Meld memiliki banyak opsi untuk membandingkan file atau direktori. Jika dua file berbeda, mudah untuk masuk ke mode perbandingan file dan melihat perbedaan yang tepat.

Alexander
sumber
2
Bagus. Saya telah menulis skrip perl sederhana untuk melakukan perbandingan di atas pohon, tetapi saya memiliki keterbatasan. Ini sepertinya adalah tiketnya.
David Tonhofer
Satu-satunya masalah adalah itu tidak cocok untuk scripting karena itu adalah aplikasi grafis. Tapi itu bagus jika Anda tidak keberatan dengan GUI! Terima kasih.
DeanM
Saya menemukan itu meldmenjadi sangat lambat jika digunakan pada direktori besar. Apakah ada yang menangani direktori besar dengan lebih baik?
Popup
@ Popup, bukan yang saya tahu. Anda dapat menemukan nama file yang berbeda dengan sesuatu seperti ini, meskipun:find dir1 dir2 | cut -d/ -f2- | sort | uniq --unique
Alexander
1
@Alexander - Dalam hal ini saya menemukan bahwa meld <(find dir1 -ls ) <(find dir2 -ls)berfungsi dengan cukup baik, menggunakan substitusi proses bash. ( =(command)Karya zsh bahkan lebih baik.)
Popup
10

'Tagihan' rekan senegaranya (dari freenode / # centos fame) membagikan metodenya kepada saya:

diff -Naur dir1/ dir2

Termasuk direktori maju slash terakhir tidak masalah.

Selain itu, tampaknya -uopsi ini tidak tersedia pada beberapa versi diff server lama.

Perbedaan dalam diffs:

# diff -Nar /tmp/dir1 /tmp/dir2/
diff -Nar /tmp/dir1/file /tmp/dir2/file
28a29
> TEST

# diff -qr /tmp/dir1/ /tmp/dir2/
Files /tmp/dir1/file and /tmp/dir2/file differ
todd_dsm
sumber
2
Jadi itulah --new-file/-Nyang membuat diff menganggap file yang hilang menjadi kosong dan --text/-ayang membuatnya menganggap semua input biner sebagai teks. Saya tidak melihat sisi positif dari use case khusus ini.
phk
4

Diffoscope adalah alat diff direktori berbasis perintah yang hebat.

Saya terutama suka tentang hal itu yang dapat berbeda menjadi file:

Itu akan secara rekursif membongkar arsip dari banyak jenis dan mengubah berbagai format biner menjadi bentuk yang lebih mudah dibaca manusia untuk membandingkannya. Itu dapat membandingkan dua tarbal, gambar ISO, atau PDF dengan mudah.

Ini tidak hanya memberi tahu Anda file mana yang berbeda, tetapi juga bagaimana mereka berbeda.

nh2
sumber
4

Untuk menemukan perbedaan, gunakan perintah ini:

diff -qr dir1/ dir2/

-r akan mengubah semua subdirektori juga -q memberitahu diff untuk melaporkan hanya ketika file berbeda.

diff  --brief dir1/ dir2/

--brief akan menampilkan file yang dosent ada di direktori.

Atau

kita dapat menggunakan Meld yang akan ditampilkan di jendela grafis yang mudah untuk menemukan perbedaannya.

meld  dir1/ dir2/
Javeed Shakeel
sumber
2
--briefdan -qmerupakan opsi yang sama. Pernyataan Anda membuatnya terdengar seperti berbeda tetapi tidak.
Elijah Lynn
2

Anda juga dapat menggunakan Rsyncdan find. Untuk find:

find $FOLDER -type f | cut -d/ -f2- | sort > /tmp/file_list_$FOLDER

Tetapi file dengan nama dan subfolder yang sama, tetapi dengan konten yang berbeda, tidak akan ditampilkan dalam daftar.

Jika Anda adalah penggemar GUI, Anda dapat memeriksa Meld yang disebutkan @Alexander . Ini berfungsi baik di windows dan linux.

Fábio
sumber
1

Untuk melaporkan perbedaan antara dirA dan dirB, sambil memperbarui / menyinkronkan.

rsync -auv <dirA> <dirB>

Kickaha
sumber