Linux: Dosyaları Karşılaştırmadan Dizin Yapısını Karşılaştırın


55

İki dizin yapısını, dosyalardaki verileri karşılaştırmadan karşılaştırmanın en iyi ve en basit yolu nedir? Bu iyi çalışıyor:

diff -qr dir1 dir2_

Ama bu gerçekten yavaştır çünkü dosyaları da karşılaştırıyor. Bunu yapmak için diff veya başka bir basit cli aracı için bir anahtar var mı?


"Dizin yapısı" ile sadece dizin yollarını mı, yoksa hem dizin hem de dizin olmayan dosyaların yollarını mı kastediyorsunuz?
intuited

Evet, klasörler ve dosyalar.
Jonah

1
Bu durumda, -type dseçeneği @ slartibartfast'ın cevabından silmelisiniz veya cevabımı kontrol etmelisiniz.
intuited

Yanıtlar:


36

Aşağıdakiler (dizin1 için ilk dizini ve dizin2 için ikincisini değiştirirseniz) aradığınızı ve hızlıca yapmalısınız:

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

Temel ilke, temel dizinN dizinlerine göre alt dizin yolları da dahil olmak üzere tüm dizinleri yazdırmasıdır.

Dizin isimlerinden bazılarında satırbaşları varsa, ancak diğerleri düşmezse, bu durum düşebilir (tuhaf çıktı üretir).


Bu benim için iyi değil, çünkü bir dizin birkaç bin dosya içeren bir klasör içeriyorsa, hepsi ayrı ayrı listelenir, diff -rqsadece kök dizin bir tanede var olduğunu gösterir ve devam eder.
Chris Jefferson

OP'lerin sorusuna cevap vermek için (yıllar önce) belirtildiği gibi, OP'lerin sorusunu yanıtlamak için -d tipi kaldırılmalıdır, böylece dosyalar dizinlerin yanı sıra karşılaştırmada da dikkate alınır
user2746401

Anladım ve sorun bildiriminin okunmasına saygı duyuyorum. O zamanlar benim okumam değildi. Güncellenen soruyu yanıtlamak için cevabımı düzenlememi tavsiye ediyor musunuz? Bazı insanlara yardımcı olacağını düşünüyorsanız, bunu yapmaktan vazgeçtim ve çözümü bırakmaktan vazgeçtim ve yorumların şu anda olduğu gibi belirlendi, ki bu da oldukça etkili görünüyor.
Slartibartfast

34
vimdiff <(cd dir1; find . | sort) <(cd dir2; find . | sort)

Ortak bölümleri katlanmış olarak, iki dizin hiyerarşisinin yan yana gösterilmesini sağlar


Bu çözüm rastgele başarısız oluyor. Vim geçici dosya tanımlayıcısını okuduğunda (veya yeniden okuduğunda), çoktan gitmiştir.
Denilson Sá Maia

23

Genelde rsyncbu görev için kullanıyorum :

rsync -nav --delete DIR1/ DIR2

Her zaman-n, aka--dry-run, seçeneğikullanmak için çok dikkatli olun, yoksa dizinleri senkronize eder (içeriğini değiştirir).

Bu, dosya değiştirme zamanları ve boyutlarına göre dosyaları karşılaştırır ... Gerçekten istediğin şeyin bu olduğunu mu düşünüyorsun , yoksa en azından bunu umursamıyor musun? Daha hızlı gerçekleşmesini istediğinizi , dosya içerikleri arasındaki farkı görmezden gelmenize gerek olmadığını anladım. Aynı ada sahip farklı dosyaları listelememesini istiyorsanız, --ignore-existingseçeneğin eklenmesinin bunu yapacağını düşünüyorum.

Ayrıca koyarak değil unutmayın /sonunda DIR1karşılaştırmak neden olur dizini DIR1 ile içindekiler arasında DIR2.

Çıktı biraz ayrıntılı olarak bitiyor, ancak size hangi dosyaların / dizinlerin farklı olduğunu gösterecek. İçinde olan DIR2ve olmayan dosyalar / dizinler DIR1sözcüğü ile ön plana çıkarılır deleting.

Bazı durumlarda, @ slartibartfast'ın cevabı daha uygun olabilir, ancak -type ddizin dışı dosyaların listesini etkinleştirmek için seçeneği kaldırmanız gerekebilir . rsyncKarşılaştıracak çok sayıda dosya / dizin varsa, daha hızlı olacaktır.


Mükemmel cevap Rsync'in çıktısında deleting...metni fark etmek zor ancak muhtemelen hızını korurken dosyaları karşılaştırmanın en iyi yollarından biri. Buradaki diğerlerinin cevapları, OP'nin örneğinde olduğu gibi dosyaları farklılaştırmak gerekmediğinde daha hızlıdır, ama bunu gerçekten seviyorum.
Joel Mellon

Peşinde olduğum şey buydu. Çok büyük dizin ağaçlarında farklı boyutlarda bazı dosyalar vardı ve hangilerinin olduğunu bilmek istedim. Bu sadece birkaç saniye içinde bu amaca ulaştı.
suprjami

Belki de salt okunur erişimi olan bir kullanıcıyla çalıştırmak iyi bir fikirdir. Gibi sudo -u nobody rsync -nav --delete d1 d2sağlanan 'başkaları' için bayraklar okuma değişimine izin verecek.
kullanici1182474,

Bu çözümü çalıştırırken "dosya listesi oluşturuldu ... bitti \ n yolladım X bayt Y bayt aldı" Z bayt / sn toplam büyüklüğü A hızlanma B "dir (burada sayılar için XYZAB kullandım). Bu her şeyin aynı olduğu anlamına mı geliyor? Daha spesifik bir şeyden bahsetmediğinden mi? Şimdiden teşekkürler
Scott H

Kendi soruma cevap vermek için her birine farklı dosyalar eklemeyi denedim ve çıktıda belirtilen belirli dosya / dizinlerin aynı olmadığı anlamına geliyor.
Scott H

18

Ls cevabına benzer fakat eğer ağaç kurarsanız

tree dir1 > out1
tree dir2 > out2
diff out1 out2

7
Ya da tmpfilfilerden kaçınmak için,diff <( tree dir1 ) <( tree dir2 )
Joel Mellon

1
iAğaç çizgilerini ( tree -i dir1, vb.) Yazdırmayan bayraklı bir ağaç çalıştırmanızı öneririm . Dizin yapısı bir yerde farklıysa, eşleşen diğer dosyalar |ağaç çıktısında az veya çok simgeye sahip olabilir ve diff, dosya yolları aynı olsa bile bu satırları yakalar.
saat

2
diff <(tree -i dir1) <(tree -i dir2), şimdiye kadarki en iyi cevaptır. Açıkça dosya içeriğini okumak DEĞİLDİR diyor, çünkü diff veya rsync öneren tüm cevapları aşağı oyluyorum. NOT: İki boru kullanma önerisi, braketler arasındaki boşlukların dikkatli kullanılmasını gerektirir, örneği tam olarak izleyin. Örneğin bir yedeklemeden sonra iki 20G birimini karşılaştırmak için ağaç cevabı yaklaşık 5 saniye sürmüştür. Diğerleri 20 dakika sürdü.
Jason Morgan,

3

Ben sadece bu problem için bir çözüm arıyordum. En sevdiğim çözüm şuydu:

comm <(ls DIR1) <(ls DIR2)

Size 3 sütun verir: 1 - sadece DIR1'deki dosyalar, 2 - sadece DIR2'deki dosyalar, 3 - sadece DIR3'deki dosyalar Daha fazla ayrıntı için bu blog gönderisine bakın.


Nerede DIR3belirtilir? Tüm gördüğüm DIR1ve DIR2.
Michael Dorst,

Ben çıkış oldu (Ne söyleyebilirim itibaren) denedim ve: tüm dosyaları sadece DIR1içinde 1. sütun , yalnızca tüm dosyaları DIR2içinde 2. sütun ve tüm dosyaları her ikisi tarafından paylaşılan de 3. sütunda . Bu yararlı olabilir, ancak birinin 3. sütunu nasıl sıyrıp yalnızca farkları bırakabileceğini biliyor musunuz? Sıralama için çok dosyam var ve çoğu aynı. Aynı olanı görmeme gerek yok.
Michael Dorst,

1
Ayrıca, comm <(ls DIR1) <(ls DIR2)özyinelemeli işe yaramadığını buldum . Bunun için kullandım comm <(ls -R1 DIR1) <(ls -R1 DIR2). ls -Rdizinleri yinelemeli olarak tarar ve ls -1( bunun bir L değil , bir tane olduğunu unutmayın ) satır başına yalnızca bir dosya adı yazdırır. ls
Michael Dorst,

@Michael: comm -3(bkz. man comm).
Zaz

2
ls > dir1.txt

ls > dir2.txt

O zaman sadece iki listeyi dağıt.


OP yolların heirarşisini istiyor gibi görünüyor. Bu, geçerli dizindeki tüm dosyaları değiştirecektir. Tartışılabilir, ancak mümkün, sadece dizin istiyor; dosyaların içeriğinden ziyade dosya isimleri isteyebilir.
sezgiler

@intuited - haklısın. Yanlış okudum.
MDMarra

2

Bu optimum çözümdür

diff --brief -r dir1 dir2

--brief switch sadece dosyaların farklılık gösterip göstermediğini, farkın detaylarını bildirmediğini gösterir.


1
OP zaten -qbir takma ad olan soruda zaten var --brief. Bu cevap herhangi bir yeni bilgi sağlamaz.
Michael Dorst,

1
OP, dosya içeriği karşılaştırmasını istemiyor. But it's really slow because it's comparing files too.
Joel Mellon

1

Farklı dosyaları almak için "diff -qr" komutunu kullanın ve ardından yalnızca dizinlerden birinde yer alan dosya adlarını almak için grep ile dosya karşılaştırmasını filtreleyin.

diff -qr dir1 dir2 | grep -v "Files.*differ" 

1

Bu, benim için eşleşmesi beklenen ağaçlardaki eksik dosyaları bulma ihtiyacım için işe yaradı.

diff <( cd dir1; find * |sort ) <(cd dir2; find * | sort)

-3

Sadece rsync'in kullanıcı dostu olduğunu düşünüyorum. neden?

diff sadece dosya ve dizinleri tutan yapılar için kullanışlıdır. Simgeler kullandığımız zaman, Diff yeterli çıkış kodları vermez. Bu durumda diff, src ve dst aynı olsa bile (çıkışlar, boyutlar, adlar, zaman damgaları, işaretleme yumuşak bağlantıları vb.) 2 çıkış kodu verebilir.

dir, dosya sistemi src ve dst üzerindeki dizin içerikleri aynı olsa bile dosya sıralamasını garanti etmez. Belki de ls çıkışını sıralayarak filtrelemelisin. Fakat salt ls sadece düğüm isimlerini gösterir.

belki diff, cmp, düğüm tipleri için test -X içeren scriptler faydalı olacaktır, fakat birçok test / cmp çalışması tarafından yapılan aşırı yükü hatırlayın. Senaryo çok yavaş olacak.

Her zamanki gibi basit bir bilgi almak istiyorsanız, "dirs aynı / özdeş değil" ise -s (dry) seçeneğiyle rsync kullanmalısınız. Neyin farklı olduğunu bulmak istiyorsanız, diff komutunu kullanın.


Neden eksi olduğunu bilmek isterim?
Znik
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.