linux diff tools: tạo danh sách các tập tin sửa đổi


14

Làm cách nào để tạo danh sách các tệp đã sửa đổi theo chương trình bằng các công cụ dòng lệnh linux? Tôi không quan tâm đến sự khác biệt trong bất kỳ tệp cụ thể nào (delta, patch). Tôi chỉ muốn có một danh sách các tệp mới hoặc sửa đổi so với bản phát hành sản phẩm trước đó. Để tôi có thể xuất bản một bản cập nhật sản phẩm mới.

cập nhật: diff -qrkhông tạo ra đầu ra rất thuận tiện. Đầu ra của diff -qrcũng cần phải được xử lý. Có cách nào tốt hơn không?


một ví dụ về đầu ra "thuận tiện" là gì?
ếchstarr78

Câu trả lời:


8

Tôi đã có một cách tiếp cận đơn giản cho việc này: Sử dụng chế độ xem trước rsync:

rsync -aHSvn --delete old_dir/ new-dir/

Các tệp được hiển thị là "sẽ bị xóa" bởi lệnh đó sẽ là các tệp "mới". Những người khác sẽ được chuyển đã thay đổi theo một cách nào đó. Xem rsync-man-page để biết thêm chi tiết.


13

Bạn có thể sử dụng công cụ tìm khác biệt : xem các tùy chọn -q và -r

-q  --brief
Output only whether files differ.

-r  --recursive
Recursively compare any subdirectories found.

Thí dụ:

diff -qr dir1 dir2

Đầu ra hoàn toàn khủng khiếp và không thể đọc được, lộn xộn với thông tin vô nghĩa nói rằng Only innó xuất hiện ngay cả khi các thư mục là bản sao lý tưởng. Tôi cần phải so sánh các thay đổi với một sửa đổi cũ và cuối cùng tải xuống toàn bộ sửa đổi vào một thư mục riêng và sử dụng các công cụ SVN tiêu chuẩn để so sánh. Đó dường như là cách duy nhất để đi
Hi-Angel

3

Các diffutilsgói bao gồm một lsdiffcông cụ. Chỉ cần chuyển đầu ra của diff -ulsdiff:

diff -u --other-diff-options path1 path2 | lsdiff

Đề nghị tốt, cảm ơn bạn. Đã có trong patchutilsgói cho tôi (CentOS 5.x).
Steve Kehlet

Yep, gói patchutils cho Ubuntu / Debian cũng vậy.
artfulrobot

1

Tôi sẽ chỉ chạm vào một tệp tại mỗi lần cập nhật và sau đó bạn có thể tìm thấy các tệp đã được sửa đổi kể từ đó với find /tree/location -newer /last/update/file -print


1

Để chỉ lấy tên của các tệp mà chúng đã thay đổi, tôi sử dụng lệnh này:

diff -r dirt1 dir2 --brief | sed 's/^Only in \([^:]*\): /\1\//' | sed 's/^Files \(.*\) and .* differ/\1/'

Nếu cần loại trừ một số tệp dưới dạng tệp đối tượng hoặc tệp thư viện, bạn có thể sử dụng:

diff -r dirt1 dir2 --brief --exclude "*.o" --exclude "*.a" | sed 's/^Only in \([^:]*\): /\1\//' | sed 's/^Files \(.*\) and .* differ/\1/'

1

Để 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 ngược lại 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 mod",
  • -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


0

Bạn sẽ nhận được kết quả mong muốn bằng cách sử dụng:

diff -r --brief dir1/ dir2/

0

Điều này có thể thực hiện các mẹo:

compare_dirs()
{
    # Shows which files and directories exist in one directory but not both
    if [ $# -ne 2 ]
    then
        echo "Usage: compare_dirs dir1 dir2" >&2
        return 2
    fi
    for path
    do
        if [ ! -d "$path" ]
        then
            echo "Not a directory: $path" >&2
            return 1
        fi
    done
    comm -3 \
        <(cd -- "$1" && find . -printf '%P\0' | sort -z | quote_shell) \
        <(cd -- "$2" && find . -printf '%P\0' | sort -z | quote_shell)
}

0

Thông thường, bạn đặt các tệp vào một số loại hệ thống kiểm soát phiên bản như SubVersion hoặc git, vì chúng có thể làm điều này cho bạn ra khỏi hộp.

Nhưng bạn có thể thực hiện một kịch bản nhanh với một vòng lặp for trên dir1 và sau đó so sánh mọi tệp với tệp trong dir2. Vòng lặp for có thể nhìn vào mã thoát từ diff để biết các tệp có khác nhau không.

Có lẽ một cái gì đó như thế này:

for f in `(cd dir1 ; find .)`
do 
  diff $f ../dir2/$f
  if [ "$?" == "0" ]
  then 
    echo same
  else 
    echo diff: $f
  fi
done

Lưu ý: Tập lệnh không được kiểm tra, vì vậy ví dụ trên là "mã giả lấy cảm hứng từ bash" ...


Chúng ta hãy đi khác nhưng với git

Tạo một số tệp ví dụ để chơi với

mkdir -p dir1/test1/test11
mkdir -p dir1/test1/test12
mkdir -p dir1/test1/test13
echo "Test1" >> dir1/test1/test11/t1.txt
echo "Test2" >> dir1/test1/test12/t2.txt
echo "Test3" >> dir1/test1/test13/t3.txt

#And a dir to work in
mkdir gitdir

Sau đó nhập dir và nhập dir1

cd gitdir/
git init .
cp -r ../dir1/* .
git add .
git commit -m 'dir1'

Đi ra ngoài và sửa đổi dir1 (để nó trở thành dir2 của bạn)

cd ..
echo "Test2" > dir1/test1/test11/t1.txt

Sau đó đi vào thư mục git và nhập thư mục mới

cd gitdir/
cp -r ../dir1/* .

Bây giờ hãy hỏi git những gì đã thay đổi (với lệnh trạng thái)

git status -s

Đầu ra là một danh sách với các thay đổi, trông như thế này:

 M test1/test11/t1.txt

0

Có lẽ bạn sẽ hạnh phúc hơn với những điều khác biệt. Hãy thử git.

Làm điều này như một ví dụ:

mkdir a
cd a
git init
touch b
git add . && git commit -m "Empty file"
git status
echo c >> b
git status
git add . && git commit -m "Full file"
git status

gitsẽ theo dõi các tập tin của bạn cho bạn. Lệnh git statussẽ hiển thị cho bạn tất cả các tệp đã được sửa đổi kể từ lần xác nhận cuối cùng.


0

Điều này tương tự với rsync: hiển thị khi tệp mới hơn về đích sẽ bị ghi đè (được hỏi sau, mặc dù không phải là bản sao).

Như đã nêu trong câu hỏi, "diff -q -r" có thể yêu cầu một số xử lý có ích. Câu hỏi không chỉ rõ hình thức của đầu ra; các câu trả lời cho các loại báo cáo khác nhau.

rsynclà một công cụ hữu ích cho mục đích này vì nó là nhiều nhanh hơn diff. Tuy nhiên, giải pháp được đề xuất bởi @nils dài dòng hơn (và liệt kê nhiều tệp hơn) so với sự khác biệt thực tế giữa các cây thư mục cũ / mới. Ví dụ: so sánh với kịch bản mà tôi đã viết cho câu trả lời đó và chạy trên cùng một dữ liệu,

  • @nils answer tạo ra 605 dòng (dường như vì nó bao gồm các thay đổi thư mục ),
  • "diff -q -r" tạo ra 352 dòng sau khi chạy trong vài phút và
  • tập lệnh của tôi hiển thị 252 dòng ( tệp thực tế đã thay đổi, thêm hoặc xóa)

Để tạo difftài khoản chính xác cho các tệp mới , bạn cũng cần -Ntùy chọn (mà tôi không thấy trong bất kỳ câu trả lời được đề xuất nào). Tuy nhiên, vì nó chậm hơn nhiều (thứ tự cường độ) so với rsync, cải thiện sản lượng của cái sau dường như là cách để đi.

đọc thêm


0

Tôi đã luôn là một phần của sha1sum (hoặc thậm chí là md5sum; trong bối cảnh này, nó khá an toàn).

find . -type f -print0 | xargs -0 md5sum | sort -k2 > /tmp/before
# don't miss the "sort" in there; it's important

# (later)
find . -type f -print0 | xargs -0 md5sum | sort -k2 > /tmp/after
vimdiff /tmp/before /tmp/after
# or whatever diff tool you like, even "diff -u"

Đôi khi - như nếu bạn có quá nhiều tệp được đổi tên hoặc di chuyển - sắp xếp trên trường đầu tiên và sau đó thực hiện tìm khác biệt có thể giúp ích, nhưng hầu hết thời gian này là đủ tốt.

Lưu ý rằng, so với một số phương pháp khác, điều này có lợi thế là bạn không cần giữ một bản sao của các tệp "trước"; chỉ tập tin đầu ra md5sum.

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.