Mặc dù sử dụng find
lệnh có thể hữu ích ở đây, bản thân shell cung cấp các tùy chọn để đạt được yêu cầu này mà không cần bất kỳ công cụ của bên thứ ba nào. Các bash
vỏ cung cấp một tùy chọn hỗ trợ glob mở rộng sử dụng mà bạn có thể lấy tên tập tin dưới đường đệ quy mà phù hợp với các phần mở rộng mà bạn muốn.
Tùy chọn mở rộng là tùy chọn extglob
cần được đặt bằng cách sử dụng shopt
tùy chọn như dưới đây. Các tùy chọn được kích hoạt với sự -s
hỗ trợ và vô hiệu hóa với -u
cờ anh ta . Ngoài ra, bạn có thể sử dụng một vài tùy chọn hơn, tức là nullglob
trong đó một quả cầu chưa từng có bị cuốn đi hoàn toàn, được thay thế bằng một tập hợp các từ không. Và globstar
điều đó cho phép lặp lại qua tất cả các thư mục
shopt -s extglob nullglob globstar
Bây giờ tất cả những gì bạn cần làm là hình thành biểu thức toàn cầu để bao gồm các tệp của một phần mở rộng nhất định mà bạn có thể làm như dưới đây. Chúng tôi sử dụng một mảng để điền vào kết quả toàn cầu vì khi được trích dẫn chính xác và mở rộng, tên tệp có ký tự đặc biệt sẽ vẫn còn nguyên và không bị hỏng do tách từ.
Ví dụ: để liệt kê tất cả các *.csv
tệp trong đường dẫn đệ quy
fileList=(**/*.csv)
Tùy chọn **
là lặp lại thông qua các thư mục con và *.csv
được mở rộng toàn cầu để bao gồm bất kỳ tệp nào của các tiện ích mở rộng được đề cập. Bây giờ để in các tập tin thực tế, chỉ cần làm
printf '%s\n' "${fileList[@]}"
Sử dụng một mảng và thực hiện một mở rộng được trích dẫn thích hợp là cách phù hợp khi được sử dụng trong các tập lệnh shell, nhưng để sử dụng tương tác, bạn có thể chỉ cần sử dụng ls
với biểu thức toàn cầu như
ls -1 -- **/*.csv
Điều này rất có thể được mở rộng để phù hợp với nhiều tệp tức là tệp kết thúc bằng nhiều phần mở rộng (nghĩa là tương tự như thêm nhiều cờ trong find
lệnh). Ví dụ xem xét một trường hợp cần để có được tất cả các file hình ảnh đệ quy tức là các phần mở rộng *.gif
, *.png
và *.jpg
, tất cả các bạn cần phải là
ls -1 -- **/+(*.jpg|*.gif|*.png)
Điều này rất có thể được mở rộng để có kết quả phủ định cũng có. Với cùng một cú pháp, người ta có thể sử dụng kết quả của toàn cầu để loại trừ các tệp thuộc loại nhất định. Giả sử bạn muốn loại trừ tên tệp với các phần mở rộng ở trên, bạn có thể làm
excludeResults=()
excludeResults=(**/!(*.jpg|*.gif|*.png))
printf '%s\n' "${excludeResults[@]}"
Cấu trúc !()
này là một hoạt động phủ định để không bao gồm bất kỳ phần mở rộng tệp nào được liệt kê bên trong và |
là một toán tử xen kẽ giống như được sử dụng trong thư viện Biểu thức chính quy mở rộng để thực hiện khớp OR của các khối.
Lưu ý rằng các hỗ trợ toàn cầu mở rộng này không có sẵn trong vỏ bourne POSIX và hoàn toàn cụ thể cho các phiên bản gần đây của bash
. Vì vậy, nếu bạn đang xem xét tính di động của các tập lệnh chạy trên POSIX và bash
shell, tùy chọn này sẽ không đúng.