Làm cách nào tôi có thể thực hiện một bản sao nếu thay đổi hoạt động của thành viên?


34

Tôi muốn sao chép một tập hợp các tệp từ thư mục A sang thư mục B, với lời cảnh báo rằng nếu một tệp trong thư mục A giống hệt với một tệp trong thư mục B, thì không nên sao chép tệp đó (và do đó không nên sửa đổi thời gian sửa đổi của nó cập nhật). Có cách nào để làm điều đó với các công cụ hiện có mà không cần viết kịch bản của riêng tôi để làm điều đó không?

Để giải thích một chút về trường hợp sử dụng của tôi: Tôi đang tự động tạo một loạt các .ctệp trong một thư mục tạm thời (bằng một phương pháp phải tạo ra tất cả chúng một cách vô điều kiện) và khi tôi tạo lại chúng, tôi chỉ muốn sao chép những cái đã thay đổi trong thư mục nguồn thực tế, khiến cho những cái không thay đổi không bị ảnh hưởng (với thời gian tạo cũ của chúng) để makebiết rằng nó không cần phải biên dịch lại chúng. (Tuy nhiên, không phải tất cả các tệp được tạo đều là .ctệp, vì vậy tôi cần thực hiện so sánh nhị phân thay vì so sánh văn bản.)

(Như một lưu ý: Điều này phát sinh từ câu hỏi tôi đã hỏi trên https://stackoverflow.com/questions/8981552/speeding-up-file-comparions-with-cmp-on-cygwin/8981762#8981762 , nơi tôi đang cố gắng để tăng tốc tập tin tập lệnh mà tôi đang sử dụng để thực hiện thao tác này, nhưng tôi thực sự nên hỏi liệu có cách nào tốt hơn để làm điều này hơn là viết tập lệnh của riêng tôi - đặc biệt là vì bất kỳ cách đơn giản nào để thực hiện việc này trong trình bao tập lệnh sẽ gọi một cái gì đó giống như cmptrên mỗi cặp tệp và bắt đầu tất cả các quy trình đó mất quá nhiều thời gian.)


1
Bạn có thể sử dụng diff -qr dirA dirBđể xem những tập tin nào là duy nhất dirAdirB, lặp đi lặp lại.

1
@ brooks-moses đây thực sự là một công việc phù hợp với ccache !
aculich

3
@hesse nếu bạn muốn hiển thị các tệp duy nhất bạn có thể sử dụng diff, nhưng nếu bạn muốn xem chỉ những gì đã thay đổi thì hãy sử dụng rsync -avnchoặc theo cách lâu dài rsync --archive --verbose --dry-run --checksum.
aculich

Câu trả lời:


29

rsync có lẽ là công cụ tốt nhất cho việc này. Có rất nhiều tùy chọn trên lệnh này để đọc trang man . Tôi nghĩ bạn muốn tùy chọn --checksum hoặc --ignore-times


Tôi nên lưu ý rằng tôi đã thử điều đó, nhưng không thành công. Cả hai tùy chọn này chỉ ảnh hưởng đến việc rsync có sao chép hay không - nhưng, ngay cả khi nó không sao chép, nó sẽ cập nhật thời gian sửa đổi của tệp mục tiêu thành giống như nguồn (nếu -ttùy chọn được chỉ định) hoặc theo thời gian đồng bộ hóa (nếu -tkhông được chỉ định).
Brooks Moses

4
@Brooks Moses: Không. Ít nhất là phiên bản của rsynctôi không. Nếu tôi làm điều này : mkdir src dest; echo a>src/a; rsync -c src/* dest; sleep 5; touch src/a; rsync -c src/* dest, thì stat dest/ahiển thị thời gian và thời gian của nó là 5 giây so với thời gian của nó src/a.
angus

@angus: Hừ. Được rồi, bạn đã đúng. Khóa này dường như là --checksumtùy chọn và mặc dù linux.die.net/man/1/rsync hoàn toàn không có ý nghĩa gì cho thấy nó có ảnh hưởng gì đến việc ngày sửa đổi có được cập nhật hay không, nhưng dù sao cũng khiến ngày sửa đổi đích bị bỏ lại hoang sơ (Mặt khác, --ignore-timestùy chọn không có hiệu ứng này; với ngày sửa đổi vẫn được cập nhật.) Mặc dù điều này dường như hoàn toàn không có giấy tờ, tuy nhiên, tôi có thể dựa vào nó không?
Brooks Moses

2
@BrooksMoses: Tôi nghĩ bạn có thể tin tưởng vào nó: rsyncquy trình làm việc của nó là: 1) kiểm tra xem tập tin có cần được cập nhật không; 2) nếu vậy, cập nhật các tập tin. Các --checksumtùy chọn nói nó không cần được cập nhật, vì vậy rsynckhông nên tiếp tục sang bước 2).
enzotib

2
@BrooksMoses: --ignore-timeskhông --checksumsao chép mọi tệp và do đó cũng cập nhật dấu thời gian, ngay cả khi các tệp giống hệt nhau.
enzotib

13

Bạn có thể sử dụng công -utắc để cpthích như vậy:

$ cp -u [source] [destination]

Từ trang người đàn ông:

   -u, --update
       copy only when the SOURCE file is newer than the destination file or 
       when the destination file is missing

4
Xin chào và chào mừng đến với trang web. Chúng tôi hy vọng câu trả lời sẽ đáng kể hơn một chút ở đây. Ví dụ, bạn có thể bao gồm một lời giải thích về những gì -ucờ làm và cách thức hoạt động và cách thức này sẽ giúp OP. Tuy nhiên, trong trường hợp cụ thể này, nó sẽ không giúp ích gì cho OP vì nó sẽ sao chép các tệp giống hệt nhau nếu chúng mới hơn và do đó thay đổi dấu thời gian của chúng, đó chính xác là điều OP muốn tránh.
terdon

1
Từ một nhận xét về một chữ A tương tự đã bị xóa: "Điều này sẽ không hoạt động vì nó cũng sao chép các tệp giống hệt nhau, nếu dấu thời gian của nguồn mới hơn (và do đó cập nhật dấu thời gian đích, theo yêu cầu của OP)."
slm

Không trả lời câu hỏi nào cả, nhưng tôi vẫn thấy nó hữu ích.
dùng31389

7

Mặc dù sử dụng rsync --checksumlà một cách tổng quát tốt để "sao chép nếu thay đổi", trong trường hợp cụ thể của bạn, có một giải pháp thậm chí còn tốt hơn!

Nếu bạn muốn tránh các tệp biên dịch lại không cần thiết, bạn nên sử dụng ccache được xây dựng cho mục đích chính xác này! Trên thực tế, nó không chỉ tránh được việc biên dịch lại các tệp được tạo tự động không cần thiết mà còn giúp tăng tốc mọi thứ bất cứ khi nào bạn thực hiện make cleanvà biên dịch lại từ đầu.

Tiếp theo tôi chắc chắn bạn sẽ hỏi, "Có an toàn không?" Vâng, vâng, như trang web chỉ ra:

Nó có an toàn không?

Vâng. Khía cạnh quan trọng nhất của bộ đệm của trình biên dịch là luôn tạo ra chính xác cùng một đầu ra mà trình biên dịch thực sẽ tạo ra. Điều này bao gồm việc cung cấp chính xác cùng một tệp đối tượng và chính xác cùng các cảnh báo của trình biên dịch sẽ được tạo nếu bạn sử dụng trình biên dịch thực. Cách duy nhất bạn có thể nói rằng bạn đang sử dụng ccache là tốc độ.

Và thật dễ dàng để sử dụng nó bằng cách chỉ cần thêm nó làm tiền tố trong CC=dòng makefile của bạn (hoặc bạn có thể sử dụng symlink, nhưng cách makefile có lẽ tốt hơn).


1
Ban đầu tôi đã hiểu lầm và nghĩ rằng bạn đang đề nghị tôi sử dụng ccache để thực hiện một phần của việc tạo, nhưng bây giờ tôi đã hiểu - đề xuất của bạn là tôi chỉ cần sao chép tất cả các tệp, sau đó sử dụng ccache trong quá trình xây dựng, do đó tránh xây dựng lại các tệp đó đã không thay đổi. Đó là một ý tưởng tốt, nhưng nó sẽ không hoạt động tốt trong trường hợp của tôi - Tôi có hàng trăm tệp, thường chỉ thay đổi một hoặc hai lần và đang chạy theo Cygwin, nơi chỉ cần bắt đầu hàng trăm quy trình ccache để xem xét mỗi tập tin sẽ mất vài phút. Tuy nhiên, được đánh giá cao bởi vì đó là một câu trả lời tốt cho hầu hết mọi người!
Brooks Moses

Không, tôi không gợi ý rằng bạn sao chép tất cả các tệp, thay vào đó bạn chỉ có thể tự động tạo các tệp .c của mình tại chỗ (xóa bước sao chép và ghi trực tiếp vào chúng). Và sau đó chỉ cần sử dụng ccache. Tôi không biết ý của bạn là gì khi bắt đầu hàng trăm quy trình ccache ... nó chỉ là một trình bao bọc nhẹ xung quanh gcc khá nhanh và cũng sẽ tăng tốc xây dựng lại các phần khác trong dự án của bạn. Bạn đã thử sử dụng nó? Tôi muốn xem một so sánh về thời gian giữa việc sử dụng phương thức sao chép của bạn với ccache. Trên thực tế, bạn có thể kết hợp cả hai phương pháp để có được lợi ích của cả hai.
aculich

1
Phải, ok, tôi hiểu về việc sao chép. Để làm rõ, điều tôi muốn nói là: Nếu tôi tạo các tệp tại chỗ, tôi phải gọi ccache file.c -o file.ohoặc tương đương, vài trăm lần vì có hàng trăm file.ctệp. Khi tôi đang làm điều đó với cmp, thay vì ccache, mất vài phút - và cmpnhẹ như ccache. Vấn đề là, trên Cygwin, bắt đầu một quy trình mất thời gian không đáng kể, ngay cả đối với một quy trình hoàn toàn không quan trọng.
Brooks Moses

1
Là một datapoint, for f in src/*; do /bin/true.exe; donemất 30 giây, vâng. Dù sao, tôi thích trình soạn thảo dựa trên Windows của mình và ngoài vấn đề thời gian này, Cygwin hoạt động khá tốt với quy trình làm việc của tôi là nơi nhẹ để kiểm tra mọi thứ cục bộ nếu tôi không tải lên máy chủ bản dựng. Thật hữu ích khi có trình bao của tôi và trình soạn thảo của tôi trong cùng một hệ điều hành. :)
Brooks Moses

1
Nếu bạn muốn sử dụng trình chỉnh sửa dựa trên Windows của mình, bạn có thể thực hiện điều đó khá dễ dàng với Shared Folders nếu bạn cài đặt Guest Additions ... nhưng này, nếu Cygwin phù hợp với bạn, tôi sẽ nói ai khác? Có vẻ như thật xấu hổ khi phải nhảy qua những cái vòng kỳ lạ như thế này ... và việc biên dịch nói chung cũng sẽ nhanh hơn trong một VM.
aculich

3

Điều này sẽ làm những gì bạn cần

diff -qr ./x ./y | awk '{print $2}' | xargs -n1 -J% cp % ./y/

Ở đâu:

  • x là thư mục mới / cập nhật của bạn
  • y là đích bạn muốn sao chép vào
  • awk sẽ lấy đối số thứ hai của mỗi dòng từ lệnh diff (có thể bạn sẽ cần thêm một số nội dung bổ sung cho tên tệp có khoảng trắng - không thể thử ngay bây giờ)
  • xargs -J% sẽ chèn tên tệp vào cp tại vị trí thích hợp

1
-1 bởi vì điều này quá phức tạp, không khả chuyển ( -Jđặc biệt là bsd; với GNU xargs -I) và không hoạt động chính xác nếu cùng một tập tin không tồn tại ở cả hai vị trí (nếu touch x/boosau đó grep cho tôi Only in ./x: boomà gây ra lỗi trong đường ống). Sử dụng một công cụ được xây dựng cho công việc, như rsync --checksum.
aculich

Hoặc tốt hơn, đối với trường hợp cụ thể này sử dụng ccache .
aculich

+1 vì đây là một tập hợp các lệnh nổi tiếng mà tôi có thể ngắt để sử dụng cho các tác vụ tương tự (đến đây để thực hiện tìm khác biệt), rsync vẫn có thể tốt hơn cho tác vụ cụ thể này
ntg

3

Tôi thích sử dụng unison để ủng hộ rsyncvì nó hỗ trợ nhiều chủ, đã thiết lập các khóa ssh và vpn riêng biệt.

Vì vậy, trong crontab của tôi chỉ có một máy chủ lưu trữ, tôi cho phép họ đồng bộ hóa cứ sau 15 phút:

* / 15 * * * * [-z "$ (pidof unison)"] && (hết thời gian 25m unison -sortbysize -ui văn bản -batch -times / home / master ssh: //192.168.1.12//home/master -path dev -logfile /tmp/sync.master.dev.log) &> /tmp/sync.master.dev.log

Sau đó, tôi có thể được phát triển ở hai bên và những thay đổi sẽ lan truyền. Trong thực tế, đối với các dự án quan trọng, tôi có tới 4 máy chủ phản chiếu cùng một cây (3 chạy unison từ cron, chỉ đến cái không có). Trên thực tế, các máy chủ Linux và Cygwin đã trộn lẫn - ngoại trừ không mong đợi các liên kết mềm trong win32 bên ngoài môi trường cygwin.

Nếu bạn đi theo con đường này, hãy tạo gương ban đầu ở phía trống mà không có -batch, tức là

unison -ui text  -times /home/master ssh://192.168.1.12//home/master -path dev

Tất nhiên có một cấu hình để bỏ qua các tập tin sao lưu, lưu trữ, vv.:

 ~/.unison/default.prf :
# Unison preferences file
ignore = Name {,.}*{.sh~}
ignore = Name {,.}*{.rb~}
ignore = Name {,.}*{.bak}
ignore = Name {,.}*{.tmp}
ignore = Name {,.}*{.txt~}
ignore = Name {,.}*{.pl~}
ignore = Name {.unison.}*
ignore = Name {,.}*{.zip}

    # Use this command for displaying diffs
    diff = diff -y -W 79 --suppress-common-lines

    ignore = Name *~
    ignore = Name .*~
    ignore = Path */pilot/backup/Archive_*
    ignore = Name *.o

Tôi đã xem xét điều đó, nhưng tôi không thể tìm thấy một unisontùy chọn có nghĩa là "không cập nhật ngày sửa đổi tập tin". Có một cái không? Mặt khác, đây là một câu trả lời tuyệt vời cho một vấn đề hoàn toàn khác.
Brooks Moses

1
-timeslàm điều đó cho tôi Unison có chế độ chạy khô quá, tôi nghĩ vậy.
Marcos

Vâng, thiết lập times=false(hoặc rời khỏi -times) sẽ làm điều đó. Tôi không biết làm thế nào tôi đã bỏ lỡ điều đó trong tài liệu trước đây. Cảm ơn!
Brooks Moses

Vui mừng được giúp đỡ. Tôi là một người gắn bó khi nói đến việc bảo tồn những thứ như modtimes, quyền và liên kết mềm. Thường bị bỏ qua
Marcos

1

Mặc dù rsync --checksumlà câu trả lời đúng, lưu ý rằng tùy chọn này không tương thích --times--archivebao gồm --times, vì vậy nếu bạn muốn rsync -a --checksum, bạn thực sự cần phải làm như vậy rsync -a --no-times --checksum.


Bạn có ý gì khi nói 'không tương thích'?
ov

Bạn có ý gì bởi "là câu trả lời đúng"?
thoni56
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.