Kırık linklerde çıktısız iki dizini diff -r ile tekrarlı olarak karşılaştırın


38

A ve bdiff -r a b dizinlerini yinelemeli olarak karşılaştırmak için kullanıyorum . Bazı kırık bağlantılar (her ikisi de aynı kırık bağlantılar olmadığını olsa sık olur a ve b dizinleri ve aynı var olmayan hedeflere işaret).

diff sonra bu durumlar için hata mesajları verir ve sıfır olmayan bir çıkış koduyla çıkar, ancak sessiz kalmasını ve dizinler kitabımda aynı olduğundan 0 ile çıkmasını istiyorum.

Bunu nasıl yapabilirim?


Yine de sembolik bağların karşılaştırılmasını mı (ve eşdeğer fakat kırılmış olarak tanımlanmasını) istiyor musunuz, yoksa bu farkın yapılmasında tüm sembolik bağları görmezden gelmek kabul edilebilir mi?
ire_and_curses

karşılaştırıldığında ve eşdeğer olarak tanımlanırsa, kırılıp kırılmaları umrumda değil. Sadece rsync'imin çalıştığını doğrulamaya çalışıyorum.
Marcus Junius Brutus

Yanıtlar:


24

3.3 veya daha sonraki sürümler için diff, Pete Harlan'ın cevabında--no-dereference açıklandığı gibi seçeneği kullanmalısınız .

Ne yazık ki eski sürümleri, diff sembolik bağlantıları görmezden gelmeyi desteklemiyor :

Bazı dosyalar dizin veya normal dosya değildir: sembolik bağlantılar, özel aygıt dosyaları, adlandırılmış yöneltmeler ve soketler gibi olağandışı dosyalardır. Şu anda diffnormal dosyalar gibi sembolik bağlantıları ele almaktadır; en üst düzeyde belirtilirse normal dosyalar gibi diğer özel dosyaları ele alır, ancak dizinleri karşılaştırırken varlıklarını bildirir. Bu, bu patchtür dosyalarda yapılan değişiklikleri temsil edemez anlamına gelir . Örneğin, hangi sembolik bağın işaret ettiği dosyayı diffdeğiştirirseniz, sembolik bağda değişiklik yapmak yerine iki dosya arasındaki farkı çıkarır.

diffisteğe bağlı olarak değişiklikleri özel dosyalara özel olarak bildirmeli ve patchbu uzantıları anlamak için genişletilmelidir.

İstediğiniz tek şey bir rsync'i doğrulamaksa (ve eksik olanı düzeltiyorsa), rsync komutunu ikinci kez çalıştırabilirsiniz. Bunu yapmak istemiyorsanız , dizini kontrol etmek yeterli olabilir.

Bunu gerçekten yapmak istiyorsanız , sembolik bağları atlamak için diffkullanabilirsiniz findve her dosya için diff'i ayrı ayrı çalıştırın. A ve b dizinlerini bağımsız değişken olarak girin:

#!/bin/bash
# Skip files in $1 which are symlinks
for f in `find $1/* ! -type l`
do
    # Suppress details of differences
    diff -rq $f $2/${f##*/}
done

veya bir astar olarak:

for f in `find a/* ! -type l`;do diff -rq $f b/${f##*/};done

Bu içindedir içerik bakımından farklılık dosyaları veya dosyaları tanımlayacaktır bir değil de b .

Bunu not et:

  • Tamamen sembolik zincirleri atladığımızdan, bu, sembolik bağlantı adlarının b . Gerekirse, tüm sembolik bağları tanımlamak için ikinci bir bulma geçişine ihtiyacınız olacak ve ardından b'deki varlıklarını açıkça kontrol etmeniz gerekecektir .
  • Listenin a içeriğinden yapıldığı için b içindeki fazladan dosyalar tanımlanmayacaktır . Bu muhtemelen senaryonuz için bir problem değildir .rsync

Önerilen komut dosyası 'a' dizininde bulunan herhangi bir dizin için tekrar tekrar çalışmaz (b / $ {f ## *} kullanarak 'b' için oluşturulan yollar doğru değildir).
Marcus Junius Brutus

@ MarcusJuniusBrutus - Evet, haklısın. Bence çözüm bir # 'yi silmek, örneğin for f in a / * bulmak! tipi l ;do echo $f b/${f#*/};done. Şu anda bunu test etmek için zamanım yok. İşe yararsa haberim olsun.
ire_and_curses

O ise hala birçok durumda filepaths haberci yukarıya daha iyi ancak. Komutun (# kaldırılmış olarak) çalışması için doğrudan bir dizinden 'a' üzerinden çağrılması gerekiyor gibi görünüyor.
Marcus Junius Brutus

Bu cevap, GNU diff 3.3'ü kullanırken eski hale gelir (aşağıdaki yazılara bakın)
Bernd Gloss

Yukarıdaki betiğin, önce tüm dosya adlarını bulması ve genişletilmiş bir komut satırına beslemesi nedeniyle birkaç sorunu vardır. (1) O zamandan beri sadece küçük dosya koleksiyonları ile çalışacaktır. (2) Özel karakterli (hatta bir boşluk) herhangi bir dosya adı işlenmez. (3) Her zaman geri $(xxx)tepme yerine kullanın . Geri tepme simetrisi onları daha az okunabilir hale getirir ve yuva yapmayı önler. 1 ve 2 ile ilgili olarak stackoverflow.com/questions/11366184/…
Stéphane Gourichon

19

Versiyon 3.3'ten beri GNU diff, sembolik bağlantıların kaldırılmasını desteklememekte, ancak daha sonra işaret ettikleri yolları karşılaştırmaktadır.

GNU diffutils> = 3.3'ü kurun ve --no-dereferenceseçeneği kullanın; bunun için kısa bir seçenek yoktur.

Eşit veya şu durumlarda tanılama sessiz olacaktır:

Sembolik bağlantılar /tmp/noderef/a/symlinkve /tmp/noderef/b/symlinkfarklı


Şimdi, içerik değişimlerini gösterirse, sembolik link düzenli bir
dosyaymış gibi

6

Daha yeni bir sürümünü kullanabilirsiniz. diff

diffGNU içinde diffutils3.3 bir içermektedir --no-dereferenceonların hedefleri yerine sembolik kendilerini karşılaştırmak sağlayan seçeneği. Farklı olduklarını bildirir, katılırlarsa sessizdir ve kırılıp kırılmamaları umrunda değil.

Seçeneğin ne zaman eklendiğini bilmiyorum; 2.8.1'de mevcut değildir.


Ben de 3.2 olduğunu teyit edebilir diff (GNU diffutils) yok
Elder Geek
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.