khác với đầu ra chỉ tên tập tin


243

Tôi đang tìm cách chạy một lệnh Linux sẽ so sánh đệ quy hai thư mục và chỉ xuất ra tên tệp của những gì khác nhau. Điều này bao gồm bất cứ điều gì có trong một thư mục chứ không phải khác hoặc ngược lại, và sự khác biệt văn bản.

Câu trả lời:


374

Từ trang diff man:

-q   Chỉ báo cáo cho dù các tập tin khác nhau, không phải là chi tiết của sự khác biệt.
-r   Khi so sánh các thư mục, so sánh đệ quy bất kỳ thư mục con nào được tìm thấy.

Lệnh ví dụ:

diff -qr dir1 dir2

Ví dụ đầu ra (phụ thuộc vào miền địa phương):

$ ls dir1 dir2
dir1:
same-file  different  only-1

dir2:
same-file  different  only-2
$ diff -qr dir1 dir2
Files dir1/different and dir2/different differ
Only in dir1: only-1
Only in dir2: only-2

Cảm ơn - difftrang hướng dẫn trong CentOS 7 mô tả -qlà "chỉ báo cáo khi các tệp khác nhau", điều này không rõ ràng hơn những gì bạn đã viết.
Chap

2
Điều này so sánh nội dung thực tế của các tệp thường là những gì người ta muốn, tuy nhiên, câu trả lời rsync cung cấp tùy chọn chỉ nhìn vào tên và kích thước của tệp chứ không phải nội dung; điều đó đôi khi là mong muốn
steveb

Hoạt động trên macOS, quá.
Marius Soutier

Ngoài ra, có thể bao gồm -x PATTERNtrong lệnh để loại trừ một số thư mục con nhất định. Ví dụ: diff -qr repo1 repo2 -x ".git" sẽ so sánh hai thư mục nhưng sẽ loại trừ đường dẫn tệp với ".git" trong đó.
ViFI

27

Bạn cũng có thể sử dụng rsync

rsync -rv --size-only --dry-run /my/source/ /my/dest/ > diff.out

6
--size-onlysẽ bỏ lỡ các tệp có kích thước giống hệt nhau nhưng nội dung khác nhau, ví dụ: old / version.txt "29a" new / version.txt "29b" . Sử dụng thay thế: rsync -ric --dry-run old/ new/trong đó đối số "-i" cho phép lấy danh sách tệp trực tiếp quarsync -ric --dry-run old/ new/ | cut -d" " -f 2
iolsmit

6
Điều này thật tuyệt nếu bạn chỉ tìm kiếm các tệp bị thiếu (đặc biệt là trên các chia sẻ mạng), nó không so sánh nội dung. Điều này giúp tôi tìm thấy một vài tệp bị lỗi khi di chuyển sang NAS mới.
OverZealous

4
Đảm bảo bao gồm dấu gạch chéo cho các đường dẫn được chỉ định trên dòng lệnh của rsync. Trong trường hợp này, điều này sẽ không hoạt động chính xác và rsync có thể sẽ liệt kê tất cả các tên tệp!
Vladimir Panteleev

2
Đối với các ý kiến ​​về việc không kiểm tra nội dung. Điều này đôi khi là mong muốn, ít nhất là vượt qua đầu tiên.
steveb

13

Nếu bạn muốn nhận danh sách các tệp chỉ trong một thư mục chứ không phải thư mục con của chúng và chỉ tên tệp của chúng:

diff -q /dir1 /dir2 | grep /dir1 | grep -E "^Only in*" | sed -n 's/[^:]*: //p'

Nếu bạn muốn liệt kê đệ quy tất cả các tệp và thư mục khác với đường dẫn đầy đủ của chúng:

diff -rq /dir1 /dir2 | grep -E "^Only in /dir1*" | sed -n 's/://p' | awk '{print $3"/"$4}'

Bằng cách này bạn có thể áp dụng các lệnh khác nhau cho tất cả các tệp.

Ví dụ: tôi có thể xóa tất cả các tệp và thư mục trong dir1 nhưng không xóa dir2:

diff -rq /dir1 /dir2 | grep -E "^Only in /dir1*" | sed -n 's/://p' | awk '{print $3"/"$4}' xargs -I {} rm -r {}

9

Trên hệ thống linux của tôi để chỉ lấy tên tệp

diff -q /dir1 /dir2|cut -f2 -d' '

7
Tôi không đặt tên tệp có khoảng trắng trên hệ thống linux của mình. ;)
gerardw

6
Tôi không có ý áp đặt điều này với bạn ... ;-p Chỉ là một gợi ý cho ai đó ...
michuelnik

không làm việc cho tôi. Cấu trúc thư mục của tôi như dưới đâyaudit-0.0.234/audit-data-warehouse-0.0.234/ audit-0.0.235/audit-data-warehouse-0.0.235/
Alex Raj Kaliamoorthy

diff -qrN /dir1 /dir2 | cut -f2 -d' 'làm việc tốt cho tôi
Francesco

9

Cách tiếp cận của việc chạy diff -qr old/ new/có một nhược điểm lớn: nó có thể bỏ lỡ các tệp trong các thư mục mới được tạo. Ví dụ, trong ví dụ bên dưới, tệp data/pages/playground/playground.txtkhông nằm trong đầu ra diff -qr old/ new/trong khi thư mục data/pages/playground/là (tìm kiếm sân chơi trong trình duyệt của bạn để so sánh nhanh). Tôi cũng đã đăng giải pháp sau đây trên Unix & Linux Stack Exchange , nhưng tôi cũng sẽ sao chép nó ở đây:

Để tạo danh sách các tệp mới hoặc sửa đổi theo chương trình, giải pháp tốt nhất tôi có thể đưa ra là sử dụng rsync , sortuniq :

(rsync -rcn --out-format="%n" old/ new/ && rsync -rcn --out-format="%n" new/ old/) | sort | uniq

Hãy để tôi giải thích với ví dụ này: chúng tôi muốn so sánh hai bản phát hành dokuwiki để xem tệp nào đã được thay đổi và tệp nào mới được tạo.

Chúng tôi lấy các tars bằng wget và trích xuất chúng vào các thư mục old/new/:

wget http://download.dokuwiki.org/src/dokuwiki/dokuwiki-2014-09-29d.tgz
wget http://download.dokuwiki.org/src/dokuwiki/dokuwiki-2014-09-29.tgz
mkdir old && tar xzf dokuwiki-2014-09-29.tgz -C old --strip-components=1
mkdir new && tar xzf dokuwiki-2014-09-29d.tgz -C new --strip-components=1

Chạy rsync một cách có thể bỏ lỡ các tệp mới được tạo khi so sánh rsync và diff hiển thị ở đây:

rsync -rcn --out-format="%n" old/ new/

mang lại sản lượng sau:

VERSION
doku.php
conf/mime.conf
inc/auth.php
inc/lang/no/lang.php
lib/plugins/acl/remote.php
lib/plugins/authplain/auth.php
lib/plugins/usermanager/admin.php

Chỉ chạy rsync theo một hướng sẽ bỏ lỡ các tệp vừa tạo và vòng khác sẽ bỏ lỡ các tệp đã bị xóa, so sánh đầu ra của diff:

diff -qr old/ new/

mang lại sản lượng sau:

Files old/VERSION and new/VERSION differ
Files old/conf/mime.conf and new/conf/mime.conf differ
Only in new/data/pages: playground
Files old/doku.php and new/doku.php differ
Files old/inc/auth.php and new/inc/auth.php differ
Files old/inc/lang/no/lang.php and new/inc/lang/no/lang.php differ
Files old/lib/plugins/acl/remote.php and new/lib/plugins/acl/remote.php differ
Files old/lib/plugins/authplain/auth.php and new/lib/plugins/authplain/auth.php differ
Files old/lib/plugins/usermanager/admin.php and new/lib/plugins/usermanager/admin.php differ

Chạy rsync cả hai cách và sắp xếp đầu ra để loại bỏ trùng lặp cho thấy thư mục data/pages/playground/và tệp data/pages/playground/playground.txtban đầu bị bỏ sót:

(rsync -rcn --out-format="%n" old/ new/ && rsync -rcn --out-format="%n" new/ old/) | sort | uniq

mang lại sản lượng sau:

VERSION
conf/mime.conf
data/pages/playground/
data/pages/playground/playground.txt
doku.php
inc/auth.php
inc/lang/no/lang.php
lib/plugins/acl/remote.php
lib/plugins/authplain/auth.php
lib/plugins/usermanager/admin.php

rsync được chạy với các đối số luận đề:

  • -r để "recurse vào thư mục",
  • -c để so sánh các tệp có kích thước giống hệt nhau và chỉ "bỏ qua dựa trên tổng kiểm tra, không phải thời gian và kích thước",
  • -n để "thực hiện chạy thử mà không có thay đổi nào được thực hiện" và
  • --out-format="%n" thành "cập nhật đầu ra bằng FORMAT được chỉ định", đó là "% n" ở đây chỉ cho tên tệp

Đầu ra (danh sách các tệp) của rsynccả hai hướng được kết hợp và sắp xếp bằng cách sử dụng sortvà danh sách được sắp xếp này sau đó được cô đọng bằng cách xóa tất cả các bản sao vớiuniq


Bạn không thể chạy nó ngược ( diff new/ old/) để xem thư mục nào đã bị xóa?
Jacques

Chạy diff -qr new/ old/trên ví dụ ở trên với các dokuwiki tars tạo ra cùng một đầu ra như diff -qr old/ new/- tức là bạn thấy rằng thư mục là mới / thiếu nhưng không phải là các tệp trong đó
iolsmit

-4
rsync -rvc --delete --size-only --dry-run source dir target dir
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.