Bạn có thể sử dụng globalstar.
Với globstartùy chọn shell được kích hoạt, tất cả những gì bạn cần là gzip -vk **/*.{css,html}.
Các Bash shell có một globstartùy chọn cho phép bạn viết đệ quy globs với **. shopt -s globstarcho phép nó. Nhưng bạn có thể không muốn làm điều đó cho các lệnh khác mà bạn chạy sau đó, vì vậy bạn có thể chạy nó và gzip lệnh của bạn trong một lớp con thay thế.
Lệnh này gziplà tất cả .cssvà .htmlcác tệp trong thư mục hiện tại bất kỳ thư mục con nào, bất kỳ thư mục con nào của chúng , v.v., giữ các tệp gốc ( -k) và cho bạn biết nó đang làm gì ( -v):
(shopt -s globstar; gzip -vk **/*.{css,html})
Nếu bạn muốn khớp tên tệp không phân biệt chữ hoa chữ thường để các phần mở rộng có một số hoặc tất cả các chữ cái viết hoa được bao gồm, thì bạn cũng có thể bật nocaseglobtùy chọn shell:
(shopt -s globstar nocaseglob; gzip -vk **/*.{css,html})
;tách hai lệnh và bên ngoài ( )khiến chúng được chạy trong một lớp con. Đặt tùy chọn shell trong subshell không khiến nó được đặt trong shell gọi. Nếu bạn làm muốn kích hoạt globstarsau đó bạn có thể chạy shopt -s globstar; sau đó bạn có thể chạy lệnh:
gzip -vk **/*.{css,html}
Bạn có thể vô hiệu hóa globstarvới shopt -u globstar. Bạn có thể kiểm tra nếu nó hiện được kích hoạt với shopt globstar.
Làm thế nào nó hoạt động
Chìa khóa để làm thế nào gziplệnh này hoạt động là shell thực hiện các mở rộng trên nó để tạo ra một danh sách của mỗi tệp trong hệ thống phân cấp thư mục với một tên phù hợp, sau đó chuyển từng tên tệp này làm đối số gzip.
- Niềng răng mở rộng biến
**/*.{css,html}thành **/*.css **/*.html.
- Sau đó, globalbing mở rộng hai mẫu đó thành tên của các tệp có thể truy cập trong thư mục hiện tại (
**do globstar) tên tệp của nó bao gồm mọi thứ ( *) theo sau là hậu tố được chỉ định ( .csshoặc .htmltrong trường hợp này).
Điều này không khớp với các tệp có tên bắt đầu bằng. hoặc các tệp nằm trong các thư mục được đặt tên theo cách này. Bạn có thể không có bất kỳ tệp HTML và CSS nào như vậy và nếu có, bạn có thể không muốn bao gồm chúng. Nhưng nếu bạn muốn bao gồm chúng, thì bạn có thể kết hợp chúng rõ ràng tùy thuộc vào nhu cầu của bạn. Ví dụ: thay đổi **/*.{css,html}để **/{,.}*.{css,html}bao gồm các tệp bắt đầu .trong khi vẫn không tìm kiếm trong các thư mục.
Nếu bạn muốn cả hai tệp có tên bắt đầu .và tệp trong thư mục có tên bắt đầu .được bao gồm, có một cách đơn giản và đơn giản hơn: bật dotglobtùy chọn shell.
(shopt -s globstar dotglob; gzip -vk **/*.{css,html})
Hoặc nếu bạn muốn kết hợp không phân biệt chữ hoa chữ thường và khớp tên tệp bắt đầu bằng .:
(shopt -s globstar nocaseglob dotglob; gzip -vk **/*.{css,html})
Mặc dù rất hiếm khi có **thể mở rộng sang thứ gì đó quá lâu.
Nếu bạn có một số lượng lớn tệp được đặt tên theo cách này, thì điều này có thể thất bại với thông báo lỗi giải thích rằng trình bao không thể xây dựng dòng lệnh vì nó sẽ quá dài. (Ngay cả với hàng ngàn tệp, điều này thường không phải là vấn đề.)
gzip sẽ không được gọi gì cả, vì vậy bạn sẽ không có được một công việc nửa vời.
Nếu lỗi này xảy ra, hoặc nếu bạn lo lắng về nó, bạn có thể sử dụng findvới -exec, như mô tả thép (với {} \;) hoặc như tôi mô tả bên dưới (với {} +).
Bạn có thể sử dụng findvới các -exechành động và +cho hiệu quả.
Các gziphỗ trợ lệnh được đưa ra tên của nhiều file được nén. Nhưng findlệnh này , mặc dù nó hoạt động tốt và sẽ không bị chậm trừ khi bạn có nhiều tệp, chạy gziplệnh một lần cho mỗi tệp:
find . \( -name \*.css -o -name \*.html \) -exec gzip -vk {} \;
Điều này hoạt động, và bạn chắc chắn có thể sử dụng nó. ( .tìm kiếm từ thư mục hiện tại. Bên cạnh đó, đó thực sự là một cách viết lệnh hơi khác trong câu trả lời rất hay của Steeldo ; bạn có thể sử dụng bất kỳ kiểu nào bạn thích.)
Bạn cũng có thể findchuyển nhiều tên tệp đến gzipvà chạy nó nhiều lần nếu cần - gần như luôn luôn chỉ một lần. Để làm điều đó, sử dụng +thay vì\; . Cuộc +tranh cãi sẽ đến ngay sau đó {}. findthay thế +bằng tên tệp bổ sung, nếu có.
find . \( -name \*.css -o -name \*.html \) -exec gzip -vk {} +
Bạn có thể sử dụng +ngay cả khi chỉ có một vài tệp phù hợp và khi có nhiều tệp trong số đó, có thể nhanh hơn đáng kể so với việc có một lệnh gzipgọi riêng cho mỗi tệp.
Như Steeldo đề cập , bạn có thể sử dụng -inamethay vì -namekhớp các tệp có tên kết thúc giống .csshoặc .htmlvới cách viết hoa khác nhau. Điều này tương ứng với việc kích hoạt nocaseglobtrong globstarphương pháp dựa trên mô tả ở trên.
Cuối cùng, bạn có thể không có bất kỳ tệp hoặc thư mục phù hợp nào bắt đầu bằng .. Nhưng nếu bạn làm, findtự động bao gồm chúng. Nếu bạn muốn loại trừ chúng (như xảy ra với globstarphương pháp dựa trên chi tiết ở trên khi dotglobtắt), bạn có thể :
find . -not -path '*/.*' \( -name \*.css -o -name \*.html \) -exec gzip -vk {} +
Cách globstardựa trên mô tả ở trên đơn giản hơn để viết, đặc biệt nếu bạn loại trừ các thư mục và tệp bắt đầu ., vì đó là mặc định.
Có gì không để làm ...
Tên tệp có thể chứa bất kỳ ký tự nào ngoại trừ dấu phân cách đường dẫn /và ký tự null . Nhiều kỹ thuật phá vỡ tên tập tin kỳ lạ tồn tại và chúng thường phức tạp hơn các kỹ thuật luôn chỉ hoạt động. Vì vậy, tôi khuyên bạn nên tránh chúng ngay cả khi bạn biết (hoặc nghĩ rằng bạn biết) họ vẫn ổn trong tình huống cụ thể của bạn. Và tất nhiên bạn phải không sử dụng chúng nếu bạn có thể có tên tập tin với các nhân vật có thể được điều trị đặc biệt, bao gồm cả khoảng trắng.
Có thể chuyển một cách an toàn đầu ra của findmột lệnh khác xử lý nó nếu bạn sử dụng -print0hoặc một hành động tương tự để khiến nó đặt ký tự null giữa các đường dẫn thay vì một dòng mới , và ngược lại. Tên tệp có thể chứa dòng mới (mặc dù tôi không khuyến khích bạn cố tình đặt tên tệp với chúng). Một findlệnh có -printhành động - bao gồm các lệnh find không có hành động rõ ràng, do đó -printlà mặc định - không tạo ra đầu ra có thể được dẫn một cách an toàn hoặc được cung cấp cho một lệnh khác thực hiện một hành động trên các tệp.
Đầu ra findtạo ra với -print0hành động có thể được dẫn đến một cách an toàn xargs -0( -0cờ cho biết xargsđầu vào được phân tách bằng null).
-rlàm việc theo thiết kế. Từ man gzip : Du lịch cấu trúc thư mục đệ quy. Nếu bất kỳ tên tệp nào được chỉ định trên dòng lệnh là thư mục , gzip sẽ xuống thư mục và nén tất cả các tệp mà nó tìm thấy ở đó (hoặc giải nén chúng trong trường hợp gunzip). (nhấn mạnh của tôi)