it-swarm-vi.com

Bộ lọc Rsync: chỉ sao chép một mẫu

Tôi đang cố gắng tạo một thư mục chứa tất cả và chỉ các tệp PDF của tôi được biên dịch từ LaTeX. Tôi thích giữ mỗi dự án trong một thư mục riêng biệt, tất cả được đặt trong một thư mục lớn có tên LaTeX. Vì vậy, tôi đã cố gắng chạy:

rsync -avn *.pdf ~/LaTeX/ ~/Output/

cần tìm tất cả các tệp pdf trong ~/LaTeX/ và chuyển chúng vào thư mục đầu ra. Điều này không hoạt động. Nó cho tôi biết nó không tìm thấy kết quả nào cho "*.pdf ". Nếu tôi rời khỏi bộ lọc này, lệnh sẽ liệt kê tất cả các tệp trong tất cả các thư mục dự án trong LaTeX. Vì vậy, đó là sự cố với bộ lọc * .pdf. Tôi đã thử thay thế ~/ với đường dẫn đầy đủ đến thư mục nhà của tôi, nhưng điều đó không có hiệu lực.

Tôi đang sử dụng zsh. Tôi đã thử làm điều tương tự trong bash và thậm chí với bộ lọc liệt kê mọi tệp duy nhất trong mỗi thư mục con ... Chuyện gì đang xảy ra ở đây?

Tại sao rsync không hiểu bộ lọc chỉ pdf của tôi?


ĐỒNG Ý. Vì vậy, cập nhật: Không tôi đang cố gắng

rsync -avn --include="*/" --include="*.pdf" LaTeX/ Output/

Và điều này cho tôi toàn bộ danh sách tập tin. Tôi đoán bởi vì mọi thứ phù hợp với mẫu đầu tiên ...

142
Seamus

TL, DR:

rsync -am --include='*.pdf' --include='*/' --exclude='*' ~/LaTeX/ ~/Output/

Rsync sao chép (các) nguồn đến đích. Nếu bạn vượt qua *.pdf dưới dạng nguồn, Shell mở rộng danh sách này thành danh sách các tệp có .pdf phần mở rộng trong thư mục hiện tại. Không có giao dịch đệ quy xảy ra vì bạn không vượt qua bất kỳ thư mục nào dưới dạng nguồn.

Vì vậy, bạn cần phải chạy rsync -a ~/LaTeX/ ~/Output/, nhưng với bộ lọc để báo cho rsync sao chép .pdf chỉ tập tin. Các quy tắc bộ lọc của Rupync có vẻ khó xử khi bạn đọc hướng dẫn, nhưng bạn có thể xây dựng nhiều ví dụ chỉ bằng một vài quy tắc đơn giản.

  • Bao gồm và loại trừ:

    • Loại trừ các tệp theo tên hoặc theo vị trí rất dễ dàng: --exclude=*~, --exclude=/some/relative/location (liên quan đến đối số nguồn, ví dụ: điều này loại trừ ~/LaTeX/some/relative/location).
    • Nếu bạn chỉ muốn khớp một vài tệp hoặc vị trí, hãy bao gồm chúng, bao gồm mọi thư mục dẫn đến chúng (ví dụ với --include=*/), sau đó loại trừ phần còn lại bằng --exclude='*'. Điều này là do:
    • Nếu bạn loại trừ một thư mục, điều này sẽ loại trừ mọi thứ bên dưới nó. Các tập tin loại trừ sẽ không được xem xét ở tất cả.
    • Nếu bạn bao gồm một thư mục, điều này không tự động bao gồm nội dung của nó. Trong các phiên bản gần đây, --include='directory/***' sẽ làm điều đó.
    • Đối với mỗi tệp, quy tắc khớp đầu tiên được áp dụng (và mọi thứ không bao giờ khớp được bao gồm).
  • Mẫu:

    • Nếu một mẫu không chứa /, nó áp dụng cho thư mục sans tên tệp.
    • Nếu một mẫu kết thúc bằng /, nó chỉ áp dụng cho các thư mục.
    • Nếu một mẫu bắt đầu bằng /, nó áp dụng cho toàn bộ đường dẫn từ thư mục được truyền dưới dạng đối số cho rsync.
    • * bất kỳ chuỗi con nào của một thành phần thư mục (nghĩa là không bao giờ khớp với /); ** phù hợp với bất kỳ chuỗi con đường dẫn.
  • Nếu một đối số nguồn kết thúc bằng dấu /, nội dung của nó được sao chép (rsync -r a/ b tạo b/foo Cho mọi a/foo). Nếu không, thư mục sẽ được sao chép (rsync -r a b tạo b/a).


Vì vậy, ở đây chúng ta cần bao gồm *.pdf, bao gồm các thư mục chứa chúng và loại trừ mọi thứ khác.

rsync -a --include='*.pdf' --include='*/' --exclude='*' ~/LaTeX/ ~/Output/

Lưu ý rằng điều này sao chép tất cả các thư mục, ngay cả những thư mục không chứa tệp phù hợp hoặc thư mục con chứa một. Điều này có thể tránh được với --Prune-empty-dirs tùy chọn (đó không phải là một giải pháp phổ quát vì sau đó bạn không thể sao chép một thư mục ngay cả bằng cách khớp nó một cách rõ ràng, nhưng đó là một yêu cầu hiếm gặp).

rsync -am --include='*.pdf' --include='*/' --exclude='*' ~/LaTeX/ ~/Output/
274
rsync -av --include="*/" --include="*.pdf" --exclude="*" ~/Latex/ ~/Output/ --dry-run

Mặc định là bao gồm mọi thứ, vì vậy bạn phải loại trừ rõ ràng mọi thứ sa bao gồm các tệp bạn muốn chuyển. Xóa --dry-run để thực sự chuyển các tệp.

Nếu bạn bắt đầu với:

--exclude '*' --include '*.pdf'

Sau đó, sự phù hợp tham lam sẽ loại trừ mọi thứ ngay lập tức.

Nếu bạn cố gắng:

--include '*.pdf' --exclude '*' 

Sau đó, chỉ các tệp pdf trong thư mục cấp cao nhất sẽ được chuyển. Nó sẽ không theo bất kỳ thư mục nào, vì những thư mục đó bị loại trừ bởi '*'.

30
jmanning2k

Nếu bạn sử dụng một mẫu như *.pdf, Shell Hồi mở rộng mô hình đó, tức là nó thay thế mẫu đó bằng tất cả các kết quả khớp trong thư mục hiện tại. Lệnh bạn đang chạy (trong trường hợp này là rsync) không biết thực tế là bạn đã cố sử dụng một mẫu.

Khi bạn đang sử dụng zsh, có một giải pháp dễ dàng: ** mẫu có thể được sử dụng để khớp các thư mục theo cách đệ quy. Thử cái này:

rsync -avn ~/LaTeX/**/*.pdf ~/Output/
15
Marcel Stimberg

Bạn có thể sử dụng find và danh sách tệp trung gian (files_to_copy) để giải quyết vấn đề của bạn. Hãy chắc chắn rằng bạn đang ở trong thư mục nhà của bạn, sau đó:

find LaTeX/ -type f -a -iname "*.pdf" > files_to_copy && rsync -avn --files-from=files_to_copy ~/ ~/Output/ && rm files_to_copy

Đã thử nghiệm với Bash.

13
Derek Frye

Đánh giá theo phần "INCLUDE/EXCLUDE PATULN RULES" của phần manpage , cách để làm điều này là

rsync -avn --include="*/" --include="*.pdf" ~/Latex/ ~/Output/

Sự khác biệt quan trọng giữa câu trả lời này và câu trả lời của kbrd là --include="*/" cờ, thông báo cho rsync đi trước và sao chép bất kỳ thư mục nào nó tìm thấy, bất cứ thứ gì chúng được đặt tên. Điều này là cần thiết bởi vì rsync sẽ không tái diễn vào thư mục con trừ khi nó được hướng dẫn sao chép thư mục con đó.

Ngoài ra, lưu ý rằng dấu ngoặc kép ngăn Shell cố gắng mở rộng các mẫu thành tên tệp so với thư mục hiện tại và thực hiện một trong các thao tác sau:

  1. Thành công và làm rối bộ lọc của bạn (không quá có khả năng ở giữa một lá cờ như thế, mặc dù bạn thực sự không bao giờ biết khi nào ai đó sẽ tạo một tệp có tên --include=foo.pdf ...)

  2. Không thành công và có khả năng tạo ra lỗi thay vì chạy lệnh (như bạn đã phát hiện ra zsh theo mặc định).

9
SamB

Đây là giải pháp ưa thích của tôi:

find source_dir -iname '*.jpg' -print0 |  rsync -0 -v --files-from=- . destination_dir/

Lệnh find dễ hiểu hơn các quy tắc bao gồm/loại trừ của rsync :-)

Nếu bạn chỉ muốn sao chép các tập tin pdf, chỉ cần thay đổi .jpg đến .pdf

3
guettli

Còn cái này thì sao:

rsync -avn --include="*.pdf" ~/Latex/ ~/Output/
3
kbyrd

Đây là một cái gì đó nên làm việc mà không cần sử dụng find. Sự khác biệt từ các câu trả lời đã được đăng là thứ tự của các quy tắc lọc. Các quy tắc lọc trong lệnh rsync hoạt động rất giống các quy tắc iptable, quy tắc đầu tiên mà tệp khớp với là quy tắc được sử dụng. Từ trang thủ công :

Khi danh sách các tệp/thư mục cần truyền được tạo, rsync sẽ kiểm tra từng tên được chuyển theo danh sách các mẫu bao gồm/loại trừ lần lượt và mẫu phù hợp đầu tiên được thực hiện: nếu đó là mẫu loại trừ, thì tệp đó là bỏ qua; nếu nó là một mẫu bao gồm thì tên tệp đó không bị bỏ qua; nếu không tìm thấy mẫu phù hợp thì tên tệp sẽ không bị bỏ qua.

Vì vậy, bạn cần một lệnh như sau:

rsync -avn --include="**.pdf" --exclude="*" ~/LaTeX/ ~/Output/

Lưu ý mẫu "**. Pdf". Theo trang nam :

nếu mẫu chứa a/(không tính dấu /) hoặc "**", thì mẫu đó được khớp với tên đường dẫn đầy đủ, bao gồm mọi thư mục hàng đầu. Nếu mẫu không có chứa một/hoặc "**", thì nó chỉ được khớp với thành phần cuối cùng của tên tệp. (Hãy nhớ rằng thuật toán được áp dụng đệ quy để "tên tệp đầy đủ" thực sự có thể là bất kỳ phần nào của đường dẫn từ thư mục bắt đầu trở xuống

Trong thử nghiệm nhỏ của tôi, điều này không hoạt động đệ quy xuống cây thư mục và chỉ chọn các tệp pdf.

2
Steven D

Để tạo thư mục chỉ chứa các tiêu đề (../include) từ bên trong thư mục nguồn:

rsync -avh --Prune-empty-dirs --exclude="build" --include="*/" --include="*.h" --exclude="*" ./* ../include/

Điều này không bao gồm tất cả các thư mục trống và thư mục build

0
SCG82