Cách sử dụng lệnh find trong Linux

Tác giả sysadmin, T.Chín 12, 2023, 01:45:02 CHIỀU

« Chủ đề trước - Chủ đề tiếp »

0 Thành viên và 1 Khách đang xem chủ đề.

Cách sử dụng lệnh find trong Linux


Sử dụng find với xargs và exec để đưa việc tìm kiếm tệp Linux của bạn lên một tầm cao mới.

  • Lệnh find của Linux là một công cụ mạnh mẽ để tìm kiếm các tệp và thư mục với nhiều tiêu chí khác nhau, chẳng hạn như loại tệp hoặc quyền sở hữu.
  • Bằng cách sử dụng lệnh find với xargs, bạn có thể chuyển kết quả tìm kiếm sang các lệnh khác để xử lý thêm.
  • Tùy chọn -exec trong lệnh find cho phép bạn gọi các chương trình bên ngoài và thực hiện xử lý bổ sung đối với tên tệp được tìm kiếm trả về.


Lệnh Linux find rất hữu ích trong việc tìm kiếm các tập tin và thư mục. Nhưng bạn cũng có thể chuyển kết quả tìm kiếm sang các chương trình khác để xử lý thêm. Chúng tôi chỉ cho bạn cách.

1. Lệnh find Linux

Lệnh Linux find rất mạnh mẽ và linh hoạt. Nó có thể tìm kiếm các tập tin và thư mục bằng cách sử dụng nhiều tiêu chí khác nhau, không chỉ tên tập tin. Ví dụ: nó có thể tìm kiếm các tệp trống, tệp thực thi hoặc tệp thuộc sở hữu của một người dùng cụ thể. Nó có thể tìm và liệt kê các tệp theo thời gian truy cập hoặc sửa đổi của chúng, bạn có thể sử dụng các mẫu biểu thức chính quy, nó đệ quy theo mặc định và nó hoạt động với các tệp giả như các đường dẫn có tên (bộ đệm FIFO).

Tất cả điều đó là vô cùng hữu ích. Lệnh khiêm tốn find thực sự chứa đựng một số sức mạnh. Nhưng có một cách để tận dụng sức mạnh đó và đưa mọi thứ lên một tầm cao mới. Nếu chúng ta có thể lấy đầu ra của find lệnh và sử dụng nó tự động làm đầu vào của các lệnh khác, thì chúng ta có thể thực hiện điều gì đó xảy ra với các tệp và thư mục được tìm thấy cho chúng ta.

Nguyên tắc chuyển đầu ra của lệnh này sang lệnh khác là đặc điểm cốt lõi của hệ điều hành có nguồn gốc từ Unix. Nguyên tắc thiết kế khiến một chương trình làm được một việc và làm tốt việc đó, đồng thời kỳ vọng rằng đầu ra của nó có thể là đầu vào của một chương trình khác - thậm chí là một chương trình chưa được viết ra - thường được mô tả là "triết lý Unix". Tuy nhiên, một số tiện ích cốt lõi, như mkdir, không chấp nhận đầu vào theo đường ống.

Để giải quyết thiếu sót này, lệnh có các tuỳ chọn xargs thể được sử dụng để phân chia đầu vào theo đường ống và đưa nó vào các lệnh khác như thể chúng là các tham số dòng lệnh cho lệnh đó. Điều này đạt được gần như tương tự như đường ống đơn giản. Đó là điều "gần giống nhau" chứ không phải là điều "hoàn toàn giống nhau" vì có thể có những khác biệt không mong muốn khi mở rộng shell và toàn cầu hóa tên tệp.

Chúng tôi sẽ cung cấp cho bạn một số ví dụ về lệnh find trên Linux để giúp minh họa một số cách sử dụng của nó.

2. Sử dụng find với xargs

Chúng ta có thể sử dụng find với tuỳ chọn xargs cho một số hành động được thực hiện trên các tệp được tìm thấy. Đây là một cách thực hiện dài dòng, nhưng chúng ta có thể cung cấp các tệp được tìm thấy bằng cách findvào xargs, sau đó chuyển chúng vào tarđể tạo tệp lưu trữ của các tệp đó. Chúng tôi sẽ chạy lệnh này trong một thư mục có nhiều tệp TRANG hệ thống trợ giúp trong đó.

Mã nguồn [Chọn]
find ./ -name "*.page" -type f -print0 | xargs -0 tar -cvzf page_files.tar.gz
Lệnh được tạo thành từ các yếu tố khác nhau.

  • find./ -name "*.page" -type f -print0 : Hành động tìm kiếm sẽ bắt đầu trong thư mục hiện tại, tìm kiếm theo tên các tệp khớp với chuỗi tìm kiếm "*.page". Các thư mục sẽ không được liệt kê vì chúng tôi đặc biệt yêu cầu nó chỉ tìm kiếm các tệp có phần mở rộng -type f. Đối print0số yêu cầu findkhông coi khoảng trắng là phần cuối của tên tệp. Điều này có nghĩa là tên tệp có dấu cách sẽ được xử lý chính xác.
  • xargs -o : -0Các đối số xargsđể không coi khoảng trắng là phần cuối của tên tệp.
  • tar -cvzf page_files.tar.gz : Đây là lệnh xargs sẽ cung cấp danh sách tệp từ findtới. Tiện ích tar sẽ tạo một tệp lưu trữ có tên "page_files.tar.gz."

Chúng ta có thể sử dụng ls để xem tệp lưu trữ được tạo cho chúng ta.

Mã nguồn [Chọn]
ls *.gz
Tệp lưu trữ được tạo cho chúng tôi. Để tính năng này hoạt động, tất cả tên tệp cần phải được chuyển cho tarhàng loạt, đó là điều đã xảy ra. Tất cả tên tệp đều được gắn thẻ ở cuối lệnh tardưới dạng một dòng lệnh rất dài.

Bạn có thể chọn để lệnh cuối cùng chạy trên tất cả các tên tệp cùng một lúc hoặc gọi một lần cho mỗi tên tệp. Chúng ta có thể thấy sự khác biệt khá dễ dàng bằng cách dẫn đầu ra từ xargstiện ích đếm dòng và ký tự wc.

Lệnh này chuyển tất cả tên tệp vào wccùng một lúc. Một cách hiệu quả, xargsxây dựng một dòng lệnh dài cho wctừng tên tệp trong đó.

Mã nguồn [Chọn]
find . -name "*.page" -type f -print0 | xargs -0 wc
Các dòng, từ và ký tự cho mỗi tệp được in cùng với tổng số cho tất cả các tệp.


Nếu chúng ta sử dụng tùy chọn xarg's -I(thay thế chuỗi) và xác định mã thông báo chuỗi thay thế — trong trường hợp này là " {}" — thì mã thông báo lần lượt được thay thế trong lệnh cuối cùng bằng từng tên tệp. Điều này có nghĩa wclà được gọi nhiều lần, một lần cho mỗi tệp.

Mã nguồn [Chọn]
find . -name "*.page" -type f -print0 | xargs -0 -I "{}" wc "{}"
Đầu ra không được xếp hàng đẹp mắt. Mỗi lệnh gọi wchoạt động trên một tệp duy nhất nên wckhông có gì để sắp xếp đầu ra. Mỗi dòng đầu ra là một dòng văn bản độc lập.


Bởi vì wc chỉ có thể cung cấp tổng số khi nó hoạt động trên nhiều tệp cùng một lúc nên chúng tôi không nhận được số liệu thống kê tóm tắt.

3. Tùy chọn -exec

Lệnh này findcó một phương thức tích hợp để gọi các chương trình bên ngoài để thực hiện xử lý thêm đối với tên tệp mà nó trả về. Tùy -execchọn (thực thi) có cú pháp tương tự nhưng khác với xargslệnh.

Mã nguồn [Chọn]
find . -name "*.page" -type f -exec wc -c "{}" \;
Điều này sẽ đếm các từ trong các tập tin phù hợp. Lệnh được tạo thành từ các yếu tố này.

  • find . : Bắt đầu tìm kiếm trong thư mục hiện tại. Lệnh này findcó tính đệ quy theo mặc định nên các thư mục con cũng sẽ được tìm kiếm.
  • -name "*.page" : Chúng tôi đang tìm kiếm các tệp có tên khớp với chuỗi tìm kiếm "*.page".
  • -type f : Chúng tôi chỉ tìm kiếm tệp chứ không phải thư mục.
  • -exec wc : Chúng ta sẽ thực thi wclệnh trên tên tệp khớp với chuỗi tìm kiếm.
  • -w : Bất kỳ tùy chọn nào bạn muốn truyền cho lệnh phải được đặt ngay sau lệnh.
  • "{}" : Phần giữ chỗ "{}" đại diện cho từng tên tệp và phải là mục cuối cùng trong danh sách tham số.
  • \;: Dấu chấm phẩy ";" được sử dụng để chỉ ra sự kết thúc của danh sách tham số. Nó phải được thoát bằng dấu gạch chéo ngược "\" để shell không diễn giải nó.

Khi chúng tôi chạy lệnh đó, chúng tôi thấy đầu ra của wc. ( -cSố byte) giới hạn đầu ra của nó ở số byte trong mỗi tệp.


Như bạn có thể thấy không có tổng số. Lệnh wc được thực thi một lần cho mỗi tên tệp. Bằng cách thay thế dấu cộng " +" cho dấu chấm phẩy kết thúc " ;" chúng ta có thể thay đổi -exec hành vi của để hoạt động trên tất cả các tệp cùng một lúc.

Mã nguồn [Chọn]
find . -name "*.page" -type f -exec wc -c "{}" \+
Chúng tôi nhận được tổng số tóm tắt và các kết quả được lập bảng rõ ràng cho chúng tôi biết tất cả các tệp đã được chuyển đến wcdưới dạng một dòng lệnh dài.


4. exec Thực sự có nghĩa là thực thi

Tùy chọn -exec (thực thi) không khởi chạy lệnh bằng cách chạy nó trong shell hiện tại. Nó sử dụng trình thực thi tích hợp của Linux để chạy lệnh, thay thế quy trình hiện tại — trình bao của bạn — bằng lệnh. Vì vậy, lệnh được khởi chạy hoàn toàn không chạy trong shell. Nếu không có shell, bạn không thể mở rộng shell các ký tự đại diện và bạn không có quyền truy cập vào các bí danh và hàm shell.

Máy tính này có một hàm shell được xác định có tên là words-only. Điều này chỉ tính các từ trong một tập tin.

Mã nguồn [Chọn]
function words-only () { wc -w $1}
Có lẽ một hàm lạ là "chỉ các từ" gõ lâu hơn nhiều so với "wc -w" nhưng ít nhất điều đó có nghĩa là bạn không cần phải nhớ các tùy chọn dòng lệnh cho wc. Chúng ta có thể kiểm tra xem nó hoạt động như thế nào:

Mã nguồn [Chọn]
words-only user_commands.pages
Điều đó chỉ hoạt động tốt với lệnh gọi dòng lệnh thông thường. Nếu chúng ta cố gắng gọi hàm đó bằng tùy chọn find -exec, nó sẽ thất bại.

Mã nguồn [Chọn]
find . -name "*.page" -type f -exec words-only "{}" \;
Đang cố gắng sử dụng hàm shell với -exec

Lệnh find không thể tìm thấy hàm shell và -exec hành động không thành công.


Để khắc phục điều này, chúng ta có thể find khởi chạy shell Bash và chuyển phần còn lại của dòng lệnh cho nó làm đối số cho shell. Chúng ta cần bọc dòng lệnh trong dấu ngoặc kép. Điều này có nghĩa là chúng ta cần thoát khỏi dấu ngoặc kép xung quanh {} chuỗi thay thế " ".

Trước khi có thể chạy find lệnh, chúng ta cần xuất hàm shell của mình bằng -f tùy chọn (dưới dạng hàm):

Mã nguồn [Chọn]
export -f words-only
Mã nguồn [Chọn]
find . -name "*.page" -type f -exec bash -c "words-only \"{}\"" \;
Điều này chạy như mong đợi.


5. Sử dụng tên tệp nhiều lần với Find

Nếu bạn muốn xâu chuỗi nhiều lệnh lại với nhau, bạn có thể làm như vậy và bạn có thể sử dụng {}chuỗi thay thế " " trong mỗi lệnh.

Mã nguồn [Chọn]
find . -name "*.page" -type f -exec bash -c "basename "{}" && words-only "{}"" \;
Nếu chúng tôi cd nâng cấp thư mục "trang" và chạy lệnh đó, find vẫn sẽ phát hiện ra các tệp TRANG vì nó tìm kiếm đệ quy. Tên tệp và đường dẫn được chuyển đến words-only hàm của chúng tôi giống như trước đây. Hoàn toàn vì lý do minh họa việc sử dụng -exechai lệnh, chúng tôi cũng đang gọi basename lệnh để xem tên tệp mà không có đường dẫn của nó.

Cả basename lệnh và words-only hàm shell đều có tên tệp được truyền cho chúng bằng {} chuỗi thay thế " ".


Có một hình phạt về tải CPU và thời gian khi liên tục gọi một lệnh trong khi bạn có thể gọi lệnh đó một lần và chuyển tất cả tên tệp cho lệnh đó cùng một lúc. Và nếu bạn gọi một shell mới mỗi lần để khởi chạy lệnh thì chi phí đó sẽ trở nên tồi tệ hơn.

Nhưng đôi khi - tùy thuộc vào điều bạn đang cố gắng đạt được - bạn có thể không có lựa chọn nào khác. Bất kể tình huống của bạn yêu cầu phương pháp nào, không ai ngạc nhiên khi Linux cung cấp đủ tùy chọn để bạn có thể tìm thấy tùy chọn phù hợp với nhu cầu cụ thể của mình.