Cegah berbeda dari memeriksa baris baru di akhir file

21

Saya memiliki dua pohon besar, yang ingin saya bandingkan. Beberapa file di pohon berbeda hanya karena satu memiliki baris baru di akhir, dan file lainnya tidak memiliki baris baru ini. Saya ingin mengabaikan fakta ini. Saya sudah mencoba menelepon diffseperti ini:

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

Dan ini berhasil. Masalah saya adalah ia juga mengabaikan perbedaan lain (yang berhubungan dengan ruang), yang mungkin penting.

Singkatnya: Saya hanya ingin mengabaikan baris baru di EOF. Apakah ini mungkin diff?

dangonfast
sumber

Jawaban:

17

Anda pada dasarnya perlu membandingkan dua file, mengabaikan byte trailing dengan syarat. Tidak ada opsi 'diff' untuk melakukan ini - tetapi ada sejumlah cara yang bisa dilakukan (misalnya, hex diff juga muncul di benak Anda.)

Untuk menggunakan 'diff', Anda pada dasarnya harus memodifikasi file yang hilang baris baru di akhir file, dan kemudian membandingkan. Anda bisa membuat direktori sementara dengan file yang dimodifikasi, atau dengan sedikit scripting, itu bisa dilakukan dalam memori. (Mengenai yang lebih disukai tergantung pada preferensi, ukuran file, jumlah file ...)

Misalnya, berikut ini akan mengubah konten file (gunakan sed -iuntuk memodifikasi di tempat, ini hanya mencetak ke stdout) untuk menambahkan baris baru jika ada yang hilang (atau biarkan file tidak berubah jika sudah ada baris baru):

sed -e '$a\'  file1.txt

Dan hanya untuk meninjau sintaks 'diff' (mengembalikan true berarti mereka sama, false berarti berbeda):

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

Verifikasi bahwa hanya spasi putih yang berbeda:

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

Dalam bash, kita dapat menggunakan 'sed' untuk memanipulasi konten file saat dilewatkan ke 'diff' (file asli tidak berubah):

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

Sekarang yang harus Anda lakukan adalah meniru diff -runtuk membandingkan direktori secara rekursif. Jika membandingkan direktori adan b, maka untuk semua file di a(misalnya, a/dir1/dir2/file.txt) turunkan path ke file di b(misalnya, b/dir1/dir2/file.txt) dan bandingkan:

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

Versi yang sedikit lebih verbose:

$ 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
michael
sumber
dapatkah Anda jelaskan apa yang sed -e '$a\'sebenarnya dilakukannya? thx
törzsmókus
jalankan sed, berikan -eskrip / ekspresi ( ) berikut , yang cocok dengan akhir file ( $), dan lakukan tindakan "append" (a \), tetapi jangan sebutkan teks apa pun (tidak ada setelah `\`) yang masih akan menambahkan EOF / baris baru ke akhir file (hanya jika itu hilang).
michael
Terima kasih. Saya belum melihat a\ .
törzsmókus
1

Saya memecahkan masalah dengan menambahkan baris baru ke masing-masing file dan mengabaikan baris kosong di diff (opsi -B). Solusi ini mungkin tidak cocok untuk kasus penggunaan Anda tetapi mungkin membantu orang lain:

echo >> $FILE1 
echo >> $FILE2
diff -B $FILE1 FILE2 
Jakob
sumber
0

Pipa output diffke grepperintah yang menjatuhkan pesan yang tidak ingin Anda lihat.

David Schwartz
sumber
tidak baik. diff -r ada dengan hasil! = 0 jika saya tidak menambahkan --ignore-semua-ruang. Untuk menjadi jelas: Saya ingin diff mengabaikan baris baru di EOF, dan hanya di EOF. Dan saya ingin melaporkan hasil yang sesuai dengan kriteria ini. Yaitu, jika file dalam pohon berbeda hanya pada baris baru di EOF, itu tidak boleh dianggap sebagai perbedaan, dan karenanya diff harus mengembalikan 0.
dangonfast
0

Pikirkan pendekatan yang berbeda juga, yang akan bekerja untuk file yang lebih besar (dan masih tidak menyalin atau memodifikasi file asli). Anda masih harus mengemulasi traversal direktori rekursif (dan ada sejumlah cara untuk melakukan itu), tetapi contoh ini tidak menggunakan 'sed', melainkan hanya membandingkan dua file, tidak termasuk byte terakhir, menggunakan cmp, misalnya,

$ 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

Masih mengulang semua file dalam direktori, dan untuk dua file a / file.txt dan b / file.txt, hitung ukuran file yang lebih besar, dan kurangi satu, lalu lakukan bilangan biner ( cmp) menggunakan jumlah byte ini (juga dalam pesta):

(( 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

Looping file akan sama dengan jawaban yang lain menggunakan seddan diff.

michael
sumber
0

Jawabannya sederhana.
Pesan tentang baris baru yang hilang tidak dalam aliran output difftetapi dalam aliran kesalahan. Jadi, bengkokkan itu ke nirwana dan kamu telah selesai untuk selamanya

diff -rqEeB fileA fileB 2> /dev/null
Yunzen
sumber
diff mengembalikan nilai! = 0 jika menemukan perbedaan dan saya ingin memeriksa nilai itu. Mengarahkan kembali ke / dev / null tidak membuat diff melupakan perbedaan itu, jadi nilai yang dikembalikan adalah! = 0, yang tidak saya inginkan. Saya ingin diff mempertimbangkan dua file yang sama jika satu-satunya perbedaan adalah baris baru terakhir
dangonfast
-1

Ada bendera di diff commnad: --strip-trailing-cryang melakukan persis seperti yang Anda minta

Dharman
sumber
-1. Sudahkah Anda mencoba ini? Ini memperlakukan /r/nseperti /ndan tidak ada hubungannya dengan ekstra /nsebelum EOF.
Kamil Maciorowski
Saya sudah mencoba ini, dan menggunakannya untuk file diff dengan dos / unix baris baru yang berbeda ... benar
Dharman
Pertanyaannya adalah tentang mengabaikan baris baru di EOF (akhir file) saja.
Kamil Maciorowski