So sánh đệ quy hai thư mục với diff -r mà không xuất ra các liên kết bị hỏng


38

Tôi đang sử dụng diff -r a bđể so sánh đệ quy các thư mục ab . Nó thường xảy ra mặc dù có một số liên kết bị hỏng (cùng một liên kết bị hỏng trong cả hai thư mục ab và trỏ đến cùng các mục tiêu không tồn tại).

Sau đó, diff đưa ra các thông báo lỗi cho các trường hợp đó và thoát với mã thoát khác không, tuy nhiên tôi muốn nó giữ im lặng và thoát với 0 vì các thư mục giống nhau trong sách của tôi.

Làm thế nào tôi có thể làm điều đó?


Bạn vẫn muốn các liên kết tượng trưng được so sánh (và được xác định là tương đương nhưng bị hỏng), hoặc có thể chấp nhận bỏ qua tất cả các liên kết tượng trưng khi thực hiện điều này khác không?
ire_and_curses

được so sánh và xác định là tương đương, tôi không quan tâm nếu chúng bị hỏng. Tôi chỉ đang cố gắng xác minh rằng rsync của tôi đã hoạt động.
Marcus Junius Brutus

Câu trả lời:


24

Đối với phiên bản 3.3 trở lên diff, bạn nên sử dụng --no-dereferencetùy chọn, như được mô tả trong câu trả lời của Pete Harlan .

Thật không may, các phiên bản cũ hơn diff không hỗ trợ bỏ qua các liên kết tượng trưng :

Một số tệp không phải là thư mục cũng không phải tệp thông thường: chúng là các tệp bất thường như liên kết tượng trưng, ​​tệp đặc biệt của thiết bị, đường ống có tên và ổ cắm. Hiện tại, diffxử lý các liên kết tượng trưng như các tệp thông thường; nó xử lý các tệp đặc biệt khác như các tệp thông thường nếu chúng được chỉ định ở cấp cao nhất, nhưng chỉ đơn giản là báo cáo sự hiện diện của chúng khi so sánh các thư mục. Điều này có nghĩa là patchkhông thể đại diện cho các thay đổi đối với các tệp như vậy. Ví dụ: nếu bạn thay đổi tệp nào liên kết tượng trưng chỉ đến, hãy đưa diffra sự khác biệt giữa hai tệp, thay vì thay đổi thành liên kết tượng trưng.

diffnên tùy ý báo cáo các thay đổi cho các tệp đặc biệt và patchnên được mở rộng để hiểu các tiện ích mở rộng này.

Nếu tất cả những gì bạn muốn là xác minh một rsync (và có lẽ sửa những gì còn thiếu), thì bạn có thể chạy lệnh rsync lần thứ hai. Nếu bạn không muốn làm điều đó, thì kiểm tra tổng hợp thư mục có thể là đủ.

Nếu bạn thực sự muốn làm điều này với diff, thì bạn có thể sử dụng findđể bỏ qua các liên kết tượng trưng và chạy diff trên từng tệp riêng lẻ. Truyền thư mục của bạn ab vào làm đối số:

#!/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

hoặc như một lớp lót:

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

Điều này sẽ xác định các tệp khác nhau về nội dung hoặc các tệp nằm trong một nhưng không phải trong b .

Lưu ý rằng:

  • vì chúng tôi đang bỏ qua hoàn toàn các liên kết tượng trưng, ​​điều này sẽ không được thông báo nếu tên liên kết tượng trưng không có trong b . Nếu bạn yêu cầu điều đó, bạn sẽ cần một lượt tìm thứ hai để xác định tất cả các liên kết tượng trưng và sau đó kiểm tra rõ ràng sự tồn tại của chúng trong b .
  • Các tập tin bổ sung trong b sẽ không được xác định, vì danh sách được xây dựng từ nội dung của a . Đây có lẽ không phải là một vấn đề cho rsynckịch bản của bạn .

Tập lệnh được đề xuất không hoạt động đệ quy cho bất kỳ thư mục nào có trong thư mục 'a' (các đường dẫn được tạo cho 'b' bằng cách sử dụng b / $ {f ## *} là không chính xác).
Marcus Junius Brutus

@MarcusJuniusBrutus - Vâng, bạn đúng. Tôi nghĩ giải pháp là xóa một #, ví dụ: for f in tìm a / *! -type l ;do echo $f b/${f#*/};done. Tôi không có thời gian để kiểm tra điều này ngay bây giờ. Cho tôi biết nếu nó hiệu quả.
ire_and_curses

tốt hơn tuy nhiên nó vẫn làm rối tung các filepath trong nhiều trường hợp. Tập lệnh (có # bị xóa) dường như cần được gọi từ một thư mục trực tiếp trên 'a' để hoạt động.
Marcus Junius Brutus

Câu trả lời này trở nên lỗi thời khi sử dụng GNU diff 3.3 (xem các bài đăng bên dưới)
Bernd Gloss

Kịch bản trên có một số vấn đề, do trước tiên tìm thấy tất cả các tên tệp và đưa chúng vào một dòng lệnh mở rộng. (1) Nó sẽ chỉ hoạt động với các bộ sưu tập nhỏ các tập tin kể từ đó. (2) Bất kỳ tên tệp nào có ký tự đặc biệt (thậm chí là khoảng trắng) sẽ không được xử lý. (3) Luôn sử dụng $(xxx)thay vì backticks. Backticks đối xứng làm cho chúng ít đọc hơn và ngăn chặn lồng nhau. Về 1 và 2, hãy xem stackoverflow.com/questions/11366184/
Stéphane Gourichon

19

Vì phiên bản 3.3 GNU diffkhông hỗ trợ các liên kết tượng trưng, ​​nhưng sau đó so sánh các đường dẫn mà chúng trỏ tới.

Cài đặt GNU diffutils> = 3.3 và sử dụng các --no-dereferencetùy chọn; không có lựa chọn ngắn cho điều đó.

Chẩn đoán sẽ im lặng nếu bằng hoặc:

Liên kết tượng trưng /tmp/noderef/a/symlink/tmp/noderef/b/symlinkkhác nhau


Bây giờ nếu chỉ nó sẽ hiển thị các thay đổi nội dung, như thể liên kết tượng trưng là một tệp thông thường ...: - /
lindes

6

Bạn có thể sử dụng phiên bản mới hơn của diff

Trong diffGNU diffutils3.3 bao gồm một --no-dereferencetùy chọn cho phép bạn tự so sánh các liên kết tượng trưng hơn là các mục tiêu của chúng. Nó báo cáo nếu chúng khác nhau, yên lặng nếu chúng đồng ý và không quan tâm liệu chúng có bị hỏng hay không.

Tôi không biết khi nào tùy chọn được thêm vào; nó không có trong 2.8.1.


Tôi có thể xác nhận là không tồn tại trong diff (GNU diffutils) 3.2
Elder Geek
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.