Diff'in dosya sonunda yeni satırı kontrol etmesini önle


21

Karşılaştırma yapmak istediğim iki büyük ağacım var. Ağaçtaki dosyalardan bazıları, birinin sonunda yeni satır olduğundan ve diğer dosyada bu satırdan yoksun olduğundan farklıdır. Bu gerçeği görmezden gelmek istiyorum. diffBöyle aramayı denedim :

diff --ignore-all-space -r <dir1> <dir2>

Ve bu çalışıyor. Benim sorunum, önemli olabilecek diğer farklılıkları (boşlukla ilgili) görmezden gelmesidir.

Özetle: Sadece EOF'deki yeni satırı yoksaymak istiyorum. Bu mümkün mü diff?

Yanıtlar:


17

Temelde takip eden baytı koşulsuz olarak göz ardı ederek iki dosyayı karşılaştırmanız gerekir. Bunu yapmak için bir 'diff' seçeneği yoktur - ancak yapılabilecek bir takım yollar vardır (örneğin, hex diff aynı zamanda akla gelir.)

'Diff' kullanmak için, temel olarak dosyanın sonunda yeni satırı eksik olan dosyaları değiştirmeniz ve sonra karşılaştırmanız gerekir. Değiştirilen dosyalarla geçici bir dizin oluşturabilir veya bellekte yapılabilecek bir miktar kod yazarak. (Tercih edildiği şekli tercihinize, dosya boyutuna, dosya sayısına bağlıdır ...)

Örneğin, aşağıdakiler bir dosyanın içeriğini ( sed -iyerinde değiştirmek için kullanın , bu sadece stdout'a yazdırır), eğer bir tane eksikse yeni bir satır eklemek için değiştirir (veya zaten bir satırsonu varsa dosyayı değiştirmez):

sed -e '$a\'  file1.txt

Ve sadece 'diff' sözdizimini gözden geçirmek için (doğru döndürmek, aynı anlamına gelir, yanlış araçlar farklıdır):

$ diff a/file1.txt   b/file1.txt  \
      && echo '** are same' || echo '** are different'
2c2
< eof
---
> eof
\ No newline at end of file
** are different

Yalnızca boşlukların farklı olduğunu doğrulayın:

$ diff --ignore-all-space  a/file1.txt   b/file1.txt \
     && echo '** are same' || echo '** are different'
** are same

Bash'da, dosya içeriğini 'diff' e iletilirken (orjinal dosyalar değişmeden kaldı) değiştirmek için 'sed' kullanabiliriz:

$ diff <(sed -e '$a\' a/file1.txt) <(sed -e '$a\' b/file1.txt) \
     && echo '** are same' || echo '** are different'
** are same

Artık tek yapmanız gereken, diff -rdizinleri yinelemeli olarak karşılaştırmak için öykünmek . Eğer dizinleri karşılaştırmak ave btüm dosyalar için daha sonra a(örneğin, a/dir1/dir2/file.txtdosyaya) derived yolu b(örneğin b/dir1/dir2/file.txt) ve karşılaştır:

$ for f in $( find a -type f  )
> do
>    diff <(sed -e '$a\' $f) <(sed -e '$a\' b/${f#*/})
> done

Biraz daha ayrıntılı bir sürüm:

$ for f in $( find a -type f  )
> do
>   f1=$f
>   f2=b/${f#*/}
>   echo "compare: $f1 $f2"
>   diff <(sed -e '$a\' $f1) <(sed -e '$a\' $f2) \
>       && echo '** are same' || echo '** are different'
> done && echo '** all are same' || echo '** all are different'
compare: a/file1.txt b/file1.txt
** are same
compare: a/file2.txt b/file2.txt
** are same
** all are same

Lütfen sed -e '$a\'tam olarak ne yaptığını açıklayabilir misiniz ? thx
törzsmókus

dosya ( ) ile eşleşen sedaşağıdaki ( -e) komut dosyasını / ifadesini çalıştırın ( $) ve "ekleme" eylemini (a \) uygulayın, ancak gerçekte herhangi bir metin belirtmeyin (`\` den sonra hiçbir şey) hala dosyanın sonuna bir EOF / newline ekleyecektir (sadece yoksa).
michael

Teşekkürler. a\ Henüz görmedim .
törzsmókus

1

Dosyaların her birine yeni bir satır ekleyerek ve diff (seçenek -B) 'te boş satırları yok sayarak sorunu çözdüm . Bu çözümler kullanım durumunuz için uygun olmayabilir, ancak başkalarına yardımcı olabilir:

echo >> $FILE1 
echo >> $FILE2
diff -B $FILE1 FILE2 

0

Çıktısını görmek istemediğiniz iletiyi bırakan diffbir grepkomuta gönderin.


iyi değil. Eğer -ignore-all-space eklemezsem diff -r sonucu! = 0 olur. Açık olmak gerekirse: EOF'daki ve sadece EOF'deki yeni satırları görmezden gelmek için diff'in aranmasını istiyorum. Ve bu kritere uyan bir sonucu rapor etmesini istiyorum. Diğer bir deyişle, ağaçtaki dosyalar yalnızca
EOF'deki yeni satırda

0

Sadece daha büyük dosyalar için de işe yarayacak farklı bir yaklaşım olduğunu düşündüm (ve hala orijinal dosyaları kopyalamıyor ya da değiştirmiyor). Hala ardışık dizin geçişini taklit etmesi gerekir (ve orada bunu birkaç yolu vardır), ancak bu örnek sed '' kullanmaz, bunun yerine sadece, son byte hariç kullanarak, iki dosyayı karşılaştırır cmp, örneğin

$ cmp  a/file1.txt  b/file1.txt  && echo '** are same' || echo '** are different'
cmp: EOF on b/file1.txt
** are different

$ du -b a/file1.txt  b/file1.txt 
13  a/file1.txt
12  b/file1.txt

$ cmp  -n 12 a/file1.txt  b/file1.txt  && echo '** are same' || echo '** are different'
** are same

Yine dizindeki tüm dosyalar üzerinde döngü yapın ve iki dosya için a / file.txt ve b / file.txt dosyalarında, daha büyük dosya boyutunu hesaplayın ve birini çıkartın, ardından cmpbu bayt sayısını kullanarak ikili bir diff ( ) yapın. bash):

(( bytes = $(du -b a/file.txt  b/file.txt  | sort -nr | head -1  | cut -f1) - 1 ))
cmp -n $bytes a/file.txt b/file.txt

Dosyaları üzerinde döngü kullanan diğer yanıtında aynı olacağını sedve diff.


0

Cevap basit.
Kayıp yeni satırla ilgili mesaj, çıkış akışında diffdeğil, hata akışındadır. Yani nirvana bük ve iyi işin bitti

diff -rqEeB fileA fileB 2> /dev/null

farklar bulursa diff bir değer döndürür! = 0 ve bu değeri kontrol etmek istiyorum. / Dev / null dizinine yönlendirmek, bu farkı unutmaya zorlamaz, bu nedenle döndürülen değer istemiyorum! Eğer tek fark son newline ise iki dosyayı eşit olarak değerlendirmek
isterim

-1

Diff commnad'da bir bayrak var: --strip-trailing-crtam olarak istediğiniz şeyi yapan


-1. Bunu denedin mi? EOF'dan hemen önce /r/ngibi davranır /nve fazladan hiçbir şey yapmaz /n.
Kamil Maciorowski

Bunu denedim ve farklı dos / unix newline ile farklı dosyalara ayırmak için kullandım ... doğru değil mi?
dharman

Soru sadece EOF'deki (dosyanın sonu) yeni satırı görmezden gelmekle ilgilidir.
Kamil Maciorowski
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.