Ngăn không cho kiểm tra dòng mới ở cuối tập tin


21

Tôi có hai cây lớn, mà tôi muốn so sánh. Một số tệp trong cây khác nhau chỉ vì một tệp có dòng mới ở cuối và tệp khác thiếu dòng mới này. Tôi muốn bỏ qua thực tế này. Tôi đã thử gọi diffnhư thế này:

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

Và điều này đang làm việc. Vấn đề của tôi là nó cũng bỏ qua những khác biệt khác (liên quan đến không gian), có thể quan trọng.

Tóm lại: Tôi chỉ muốn bỏ qua dòng mới tại EOF. Điều này có thể với diff?

Câu trả lời:


17

Về cơ bản, bạn cần so sánh hai tệp, bỏ qua điều kiện byte theo dõi. Không có tùy chọn 'diff' để làm điều này - nhưng có một số cách có thể được thực hiện (ví dụ, hex diff cũng xuất hiện trong đầu.)

Để sử dụng 'diff', về cơ bản, bạn phải sửa đổi các tệp bị thiếu dòng mới ở cuối tệp và sau đó so sánh. Bạn có thể tạo một thư mục tạm thời với các tệp đã sửa đổi hoặc với một chút kịch bản có thể được thực hiện trong bộ nhớ. (Việc được ưu tiên tùy thuộc vào sở thích, kích thước tệp, số lượng tệp ...)

Ví dụ: phần sau đây sẽ sửa đổi nội dung của tệp (sử dụng sed -iđể sửa đổi tại chỗ, phần này chỉ in ra thiết bị xuất chuẩn) để thêm dòng mới nếu thiếu (hoặc giữ nguyên tệp nếu đã có dòng mới):

sed -e '$a\'  file1.txt

Và chỉ để xem lại cú pháp 'diff' (trả về true có nghĩa là chúng giống nhau, false có nghĩa khác nhau):

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

Xác minh rằng chỉ có khoảng trắng là khác nhau:

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

Trong bash, chúng ta có thể sử dụng 'sed' để thao tác nội dung tệp khi nó được chuyển đến 'diff' (các tệp gốc không thay đổi):

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

Bây giờ tất cả bạn phải làm là mô phỏng diff -rđể so sánh đệ quy các thư mục. Nếu so sánh các thư mục ab, sau đó cho tất cả các tệp trong a(ví dụ a/dir1/dir2/file.txt:) dẫn xuất đường dẫn đến tệp trong b(ví dụ b/dir1/dir2/file.txt:) và so sánh:

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

Một phiên bản dài hơn một chút:

$ 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

bạn có thể vui lòng giải thích sed -e '$a\'chính xác những gì làm? thx
törzsmókus

chạy sed, đưa ra -etập lệnh / biểu thức ( ) phù hợp với phần cuối của tệp ( $) và thực hiện hành động "chắp thêm" (a \), nhưng thực tế không chỉ định bất kỳ văn bản nào (không có gì sau `\`) vẫn sẽ thêm một EOF / dòng mới vào cuối tệp (chỉ khi nó bị thiếu).
michael

cám ơn. Tôi chưa thấy a\ .
törzsmókus

1

Tôi đã giải quyết vấn đề bằng cách thêm một dòng mới vào mỗi tệp và bỏ qua các dòng trống trong tùy chọn khác (tùy chọn -B). Giải pháp này có thể không phù hợp với trường hợp sử dụng của bạn nhưng nó có thể giúp người khác:

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

0

Chuyển đầu ra của lệnh diffthành một grepthông báo mà bạn không muốn xem.


không tốt. diff -r tồn tại với kết quả! = 0 nếu tôi không thêm --ignore-all-space. Để rõ ràng: Tôi muốn diff bỏ qua các dòng mới tại EOF, và chỉ tại EOF. Và tôi muốn nó báo cáo một kết quả phù hợp với tiêu chí này. Đó là, nếu các tệp trong cây chỉ khác nhau trên dòng mới tại EOF, thì đó không phải được coi là khác biệt và do đó diff phải trả về 0.
dangonfast

0

Chỉ cần nghĩ về một cách tiếp cận khác, nó sẽ hoạt động cho các tệp lớn hơn (và vẫn không sao chép hoặc sửa đổi các tệp gốc). Bạn vẫn sẽ phải mô phỏng thư mục đệ quy (và có một số cách để làm điều đó), nhưng ví dụ này không sử dụng 'sed', mà chỉ so sánh hai tệp, ngoại trừ byte cuối cùng, sử dụng cmp, ví dụ:

$ 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

Vẫn lặp trên tất cả các tệp trong thư mục và đối với hai tệp a / file.txt và b / file.txt, hãy tính kích thước tệp lớn hơn và trừ đi một tệp, sau đó thực hiện một diff nhị phân ( cmp) bằng cách sử dụng số byte này (cũng trong 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

Vòng lặp trên các tệp sẽ giống như trong câu trả lời khác sử dụng seddiff.


0

Đáp án đơn giản.
Thông báo về dòng mới bị thiếu không nằm trong luồng đầu ra diffmà là trong luồng lỗi. Vì vậy, uốn cong nó đến niết bàn và bạn đã hoàn thành tốt

diff -rqEeB fileA fileB 2> /dev/null

diff trả về một giá trị! = 0 nếu nó tìm thấy sự khác biệt và tôi muốn kiểm tra giá trị đó. Chuyển hướng đến / dev / null không làm cho diff quên đi sự khác biệt đó, vì vậy giá trị được trả về là! = 0, điều mà tôi không muốn. Tôi muốn diff xem xét hai tệp bằng nhau nếu sự khác biệt duy nhất là dòng mới nhất
dangonfast

-1

Có một lá cờ trong diff commnad: --strip-trailing-crlàm chính xác những gì bạn yêu cầu


-1. Bạn đã thử điều này? Nó xử lý /r/nnhư thế nào /nvà không có gì để làm với thêm /nngay trước EOF.
Kamil Maciorowski

Tôi đã thử điều này và đã sử dụng nó để tập tin khác với dòng mới dos / unix khác nhau ... không đúng sao?
dharman

Câu hỏi là về việc bỏ qua dòng mới tại EOF (cuối tệp).
Kamil Maciorowski
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.