Linux: So sánh cấu trúc thư mục mà không so sánh các tệp


55

Cách tốt nhất và đơn giản nhất để so sánh hai cấu trúc thư mục mà không thực sự so sánh dữ liệu trong các tệp là gì? Điều này hoạt động tốt:

diff -qr dir1 dir2_

Nhưng nó thực sự chậm vì nó cũng so sánh các tập tin. Có một công tắc cho diff hoặc một công cụ cli đơn giản khác để làm điều này?


Theo "cấu trúc thư mục", bạn có nghĩa chỉ là các đường dẫn thư mục, hoặc các đường dẫn của cả hai tệp thư mục và không phải thư mục?
trực giác

Có, thư mục tập tin.
Giô-na

1
Trong trường hợp đó, bạn nên xóa -type dtùy chọn khỏi câu trả lời của @ slartibartfast hoặc xem câu trả lời của tôi.
trực giác

Câu trả lời:


36

Việc sau (nếu bạn thay thế thư mục đầu tiên cho thư mục1 và thư mục thứ hai cho thư mục 2) sẽ thực hiện những gì bạn đang tìm kiếm và nhanh chóng:

find directory1 -type d -printf "%P\n" | sort > file1
find directory2 -type d -printf "%P\n" | sort | diff - file1

Nguyên tắc cơ bản là nó in ra tất cả các thư mục bao gồm các đường dẫn thư mục con liên quan đến các thư mục cơ sởN.

Điều này có thể rơi xuống (tạo ra đầu ra wierd) nếu bạn có lợi nhuận vận chuyển trong một số tên thư mục nhưng không phải tên khác.


Điều này không tốt cho tôi, bởi vì nếu một thư mục chứa một thư mục chứa vài nghìn tệp thì tất cả đều được liệt kê riêng lẻ, trong khi diff -rqchỉ hiển thị thư mục gốc tồn tại trong một và tiếp tục.
Chris Jefferson

Như đã chỉ ra (nhiều năm trước) bởi trực giác, để trả lời câu hỏi OP, nên loại bỏ -type để các tệp được xem xét trong so sánh cũng như các thư mục
user2746401

Tôi hiểu và tôn trọng rằng đọc các tuyên bố vấn đề. Đó không phải là đọc của tôi tại thời điểm đó. Bạn có đề nghị tôi chỉnh sửa câu trả lời của mình để trả lời câu hỏi cập nhật không? Tôi ổn khi làm điều đó nếu bạn nghĩ rằng nó sẽ hữu ích cho một số người, và tôi ổn khi để lại giải pháp và nhận xét theo cách hiện tại, điều này dường như có hiệu quả hợp lý.
Slartibartfast

34
vimdiff <(cd dir1; find . | sort) <(cd dir2; find . | sort)

sẽ cung cấp cho bạn một màn hình hiển thị song song của hai cấu trúc phân cấp thư mục với bất kỳ phần chung nào được gấp lại.


Giải pháp này thất bại ngẫu nhiên. Khi vim đọc (hoặc đọc lại) bộ mô tả tệp tạm thời, nó đã biến mất.
Denilson Sá Maia

23

Tôi thường sử dụng rsynccho nhiệm vụ này:

rsync -nav --delete DIR1/ DIR2

HÃY CẨN THẬN để luôn luôn sử dụngtùy chọn,-naka--dry-run, hoặc nó sẽ đồng bộ hóa (thay đổi nội dung của) các thư mục.

Điều này sẽ so sánh các tệp dựa trên thời gian và kích thước sửa đổi tệp ... Tôi nghĩ đó là những gì bạn thực sự muốn, hoặc ít nhất bạn không bận tâm nếu nó làm điều đó? Tôi có cảm giác rằng bạn chỉ muốn nó xảy ra nhanh hơn , không phải là bạn cần nó để bỏ qua sự khác biệt giữa các nội dung tập tin. Nếu bạn muốn nó không liệt kê các tệp khác nhau có tên giống nhau, tôi nghĩ rằng việc thêm --ignore-existingtùy chọn sẽ làm điều đó.

Cũng cần lưu ý rằng việc không đặt dấu /ở cuối DIR1sẽ khiến nó so sánh thư mục DIR1 với nội dung của DIR2.

Đầu ra cuối cùng là một chút dài dòng, nhưng nó sẽ cho bạn thấy các tập tin / thư mục khác nhau. Các tập tin / thư mục có trong DIR2và không có DIR1sẽ được mở đầu bằng từ này deleting.

Đối với một số trường hợp, câu trả lời của @ slartibartfast có thể phù hợp hơn, mặc dù bạn sẽ cần xóa -type dtùy chọn để bật danh sách các tệp không phải thư mục. rsyncsẽ nhanh hơn nếu bạn có một số lượng đáng kể các tệp / thư mục để so sánh.


Câu trả lời tuyệt vời. Trong đầu ra của rsync, thật khó để nhận thấy deleting...văn bản nhưng có lẽ đó là một trong những cách tốt hơn để so sánh các tệp trong khi vẫn duy trì tốc độ. Các câu trả lời khác ở đây nhanh hơn khi các tệp khác nhau không bắt buộc ... như trong ví dụ của OP, nhưng tôi thực sự thích cái này.
Joel Mellon

Đây là những gì tôi đã sau. Tôi đã có một số tệp với các kích cỡ khác nhau trong một cặp cây thư mục lớn và tôi muốn biết đó là những tệp nào. Điều này đạt được mục tiêu đó chỉ trong vài giây.
suprjami

Có lẽ đó là một ý tưởng tốt để chạy nó với người dùng có quyền truy cập chỉ đọc. Giống như sudo -u nobody rsync -nav --delete d1 d2với điều kiện là các cờ cho 'người khác' cho phép đọc.
dùng1182474

Khi chạy giải pháp này, tôi nhận được "danh sách tệp xây dựng ... đã hoàn thành gửi n byte X nhận được Y byte Z byte / giây tổng kích thước là A speedup là B" (trong đó tôi thay thế XYZAB cho các số). Điều đó có nghĩa là mọi thứ đều giống hệt nhau? Vì nó không đề cập gì cụ thể hơn? Cảm ơn trước
Scott H

Để trả lời câu hỏi của riêng tôi, tôi đã thử nghiệm thêm các tệp khác nhau cho mỗi tệp và dường như không có tệp / thư mục cụ thể nào được đề cập trong đầu ra có nghĩa là tất cả chúng đều giống nhau.
Scott H

18

Tương tự như câu trả lời ls nhưng nếu bạn cài đặt cây thì bạn có thể

tree dir1 > out1
tree dir2 > out2
diff out1 out2

7
Hoặc để tránh các tmpfiles,diff <( tree dir1 ) <( tree dir2 )
Joel Mellon

1
Tôi khuyên bạn nên chạy cây với icờ, không in các dòng cây ( tree -i dir1, v.v.). Nếu cấu trúc thư mục khác nhau ở một nơi, các tệp khác khớp có thể có nhiều hoặc ít |ký hiệu trong đầu ra của cây và diff sẽ bắt các dòng đó ngay cả khi các đường dẫn tệp giống hệt nhau.
askewchan

2
diff <(cây -i dir1) <(cây -i dir2) cho đến nay là câu trả lời tốt nhất. Tôi mong muốn hạ thấp tất cả các câu trả lời đề xuất diff hoặc rsync như câu hỏi nói rõ ràng KHÔNG đọc nội dung tệp. LƯU Ý: Đề xuất sử dụng hai ống yêu cầu sử dụng cẩn thận khoảng trắng giữa các dấu ngoặc, hãy làm theo ví dụ chính xác. Ví dụ, để so sánh hai khối lượng 20G sau khi sao lưu, câu trả lời của cây mất khoảng 5 giây. Những người khác mất hơn 20 phút.
Jason Morgan

3

Tôi chỉ tìm kiếm giải pháp cho vấn đề này. Giải pháp mà tôi thích nhất là:

comm <(ls DIR1) <(ls DIR2)

Nó cung cấp cho bạn 3 cột: 1 - tệp chỉ trong DIR1, 2 - tệp chỉ trong DIR2, 3 - tệp chỉ trong DIR3 Để biết thêm chi tiết, hãy xem bài đăng trên blog này .


Trường hợp được DIR3chỉ định? Tất cả những gì tôi thấy là DIR1DIR2.
Michael Dorst

Tôi đã thử nó và (từ những gì tôi có thể nói) đầu ra là: tất cả các tệp chỉ DIR1trong cột 1 , tất cả các tệp chỉ DIR2trong cột 2 và tất cả các tệp được chia sẻ bởi cả hai trong cột 3 . Điều đó rất hữu ích, nhưng bạn có biết làm thế nào người ta có thể loại bỏ cột 3 và chỉ để lại sự khác biệt không? Tôi có rất nhiều tập tin để sắp xếp, và hầu hết là giống hệt nhau. Tôi không cần phải xem những gì giống nhau.
Michael Dorst

1
Ngoài ra, tôi thấy rằng comm <(ls DIR1) <(ls DIR2)đã không làm việc đệ quy. Cho rằng tôi đã sử dụng comm <(ls -R1 DIR1) <(ls -R1 DIR2). ls -Rbóc tách thông qua các thư mục đệ quy, và ls -1(lưu ý rằng đó là một ai , không một L ) làm cho lsin chỉ có một tên tập tin trên mỗi dòng.
Michael Dorst

@Michael: comm -3(xem man comm).
Zaz

2
ls > dir1.txt

ls > dir2.txt

Sau đó chỉ cần khác hai danh sách.


Có vẻ như OP muốn một người thừa kế các con đường. Điều này sẽ khác tất cả các tập tin trong thư mục hiện tại. Thật đáng tranh luận, nhưng có thể, rằng anh ta chỉ muốn các thư mục; anh ta có thể muốn tên tập tin hơn là nội dung của tập tin.
trực giác

@intuited - bạn nói đúng. Tôi đọc sai nó.
MDMarra

2

Đây là giải pháp tối ưu

diff --brief -r dir1 dir2

--brief switch chỉ báo cáo xem các tệp có khác nhau không chứ không phải chi tiết về chênh lệch.


1
OP đã có -qtrong câu hỏi, đó là một bí danh cho --brief. Câu trả lời này không cung cấp bất kỳ thông tin mới.
Michael Dorst

1
OP không muốn so sánh nội dung tập tin. But it's really slow because it's comparing files too.
Joel Mellon

1

sử dụng "diff -qr" để lấy các tệp khác nhau và sau đó lọc ra so sánh tệp với grep để chỉ lấy tên tệp chỉ có trong một trong các thư mục.

diff -qr dir1 dir2 | grep -v "Files.*differ" 

1

Điều này làm việc cho nhu cầu cụ thể của tôi để tìm các tệp bị thiếu trong cây dự kiến ​​phù hợp.

diff <( cd dir1; find * |sort ) <(cd dir2; find * | sort)

-3

Tôi nghĩ rằng chỉ rsync là người dùng đầy đủ. tại sao?

diff chỉ hữu ích cho các cấu trúc lưu giữ các tập tin và thư mục. Diff không cung cấp mã thoát đầy đủ khi chúng tôi sử dụng symlink. Trong tình huống đó, diff có thể trả về 2 mã thoát, ngay cả khi src và dst giống hệt nhau (thời gian, kích thước, tên, dấu thời gian, liên kết mềm, v.v.).

dir, hệ thống tập tin không đảm bảo thứ tự tập tin, ngay cả khi nội dung thư mục trên src và dst giống hệt nhau. Có lẽ bạn nên lọc đầu ra ls bằng cách sắp xếp nó. Nhưng ls thuần chỉ hiển thị tên nút.

có thể tập lệnh bao gồm diff, cmp, test -X cho các loại nút sẽ hữu ích, nhưng hãy nhớ về tình trạng quá tải được thực hiện bởi nhiều lần chạy test / cmp. Kịch bản sẽ rất chậm.

Như thường lệ, nếu bạn muốn nhận thông tin đơn giản "thư mục là / không giống nhau", bạn nên sử dụng rsync với tùy chọn -n (khô). Nếu bạn muốn tìm những gì khác biệt, hãy sử dụng lệnh diff.


Tôi muốn biết tại sao trừ?
Znik
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.