Linux find
lệnh rất tốt trong việc tìm kiếm các tệp và thư mục. Nhưng bạn cũng có thể chuyển kết quả tìm kiếm cho các chương trình khác để xử lý thêm. Chúng tôi chỉ cho bạn cách làm.
Lệnh tìm Linux
Linux find
lệnh mạnh mẽ và linh hoạt. Nó có thể tìm kiếm các tệp 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. Ví dụ: nó có thể tìm kiếm các tệp trống, tệp thực thi hoặc tệp do một người dùng cụ thể sở hữu. Nó có thể tìm và liệt kê các tệp theo thời gian được truy cập hoặc sửa đổi của chúng, bạn có thể sử dụng các mẫu regex, nó là đệ quy theo mặc định và nó hoạt động với các tệp giả như đường ống được đặt tên (bộ đệm FIFO).
Tất cả những điều đó đều vô cùng hữu ích. Người khiêm tốn find
lệnh thực sự đóng gói 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 cấp độ khác. Nếu chúng ta có thể lấy đầu ra của find
và sử dụng nó tự động làm đầu vào của các lệnh khác, 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 mà chúng ta tìm thấy phần phát hiện.
Nguyên tắc nối đầu ra của một lệnh này thành một lệnh khác là một đặc điểm cốt lõi của hệ điều hành Unix. Nguyên tắc thiết kế của việc tạo ra một chương trình làm một việc và làm tốt điều đó, và 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”. Và một số tiện ích cốt lõi, như mkdir
không chấp nhận đầu vào bằng đường ống.
Để giải quyết vấn đề này, xargs
lệnh có 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 như giống nhau”, và không phải là điều “hoàn toàn giống nhau” bởi vì có thể có sự khác biệt bất ngờ với việc mở rộng shell và tên tệp được lấp đầy.
Sử dụng find With xargs
Chúng ta có thể sử dụng find
với xargs
đối với 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 dài hơi để thực hiện nó, nhưng chúng tôi có thể cung cấp các tệp được tìm thấy bởi find
vào trong xargs
sau đó đưa chúng vào tar
để tạo một 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 PAGE hệ thống trợ giúp trong đó.
find ./ -name "*.page" -type f -print0 | xargs -0 tar -cvzf page_files.tar.gz
Lệnh được tạo thành từ các phần tử khác nhau.
-
tìm ./ -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 cho các tệp phù hợp với chuỗi tìm kiếm “* .page”. Các thư mục sẽ không được liệt kê bởi vì chúng tôi đặc biệt yêu cầu nó chỉ tìm kiếm các tệp, với
-type f
. Cácprint0
đối số nói vớifind
để khô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à các tên tệp có khoảng trắng trong đó sẽ được xử lý chính xác. -
xargs -o: Các
-0
tranh luậnxargs
để 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ừfind
đến. 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 tôi.
ls *.gz
Tệp lưu trữ được tạo cho chúng tôi. Để điều này hoạt động, tất cả các tên tệp cần phải được chuyển cho tar
en masse, đó là những gì đã xảy ra. Tất cả các tên tệp đã được gắn thẻ vào cuối tar
lệnh như 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 đượ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 đặt đầu ra từ xargs
đến tiện ích đếm dòng và ký tự wc
.
Lệnh này chuyển tất cả các tên tệp vào wc
một lần. Có hiệu quả, xargs
xây dựng một dòng lệnh dài cho wc
với mỗi tên tệp trong đó.
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 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 ” {}
“- 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 là wc
được gọi nhiều lần, một lần cho mỗi tệp.
find . -name "*.page" -type f -print0 | xargs -0 -I "{}" wc "{}"
Đầu ra không được xếp thẳng hàng. Mỗi lời gọi wc
hoạt động trên một tệp duy nhất nên wc
không có gì để xếp hàng đầu ra. Mỗi dòng đầu ra là một dòng văn bản độc lập.
Tạ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, chúng tôi không nhận được thống kê tóm tắt.
Tùy chọn tìm -exec
Các find
lệnh có sẵn một phương thức gọi các chương trình bên ngoài để thực hiện xử lý thêm các tên tệp mà nó trả về. Các -exec
(thực thi) có cú pháp tương tự nhưng khác với xargs
yêu cầu.
find . -name "*.page" -type f -exec wc -c "{}" ;
Điều này sẽ đếm các từ trong các tệp phù hợp. Lệnh được tạo thành từ các phần tử này.
-
tìm thấy .: Bắt đầu tìm kiếm trong thư mục hiện tại. Các
find
lệnh là đệ quy theo mặc định, vì vậy 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, không phải thư mục.
-
-exec wc: Chúng tôi sẽ thực hiện
wc
lệnh trên tên tệp được khớp với chuỗi tìm kiếm. - -w: Bất kỳ tùy chọn nào bạn muốn chuyển đến 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 phần cuối 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
. Các -c
(số lượng 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ố. Các wc
lệnh được thực hiện một lần cho mỗi tên tệp. Bằng cách thay thế một dấu cộng “+
“Cho dấu chấm phẩy kết thúc”;
”Chúng ta có thể thay đổi -exec
hoạt động của tất cả các tệp cùng một lúc.
find . -name "*.page" -type f -exec wc -c "{}" +
Chúng tôi nhận được tổng số tóm tắt và kết quả được lập bảng gọn gàng cho chúng tôi biết tất cả các tệp đã được chuyển đến wc
như một dòng lệnh dài.
thực thi Thực sự có nghĩa là thực thi
Các -exec
(thực thi) tùy chọn không khởi chạy lệnh bằng cách chạy nó trong trình bao hiện tại. Nó sử dụng tệp thi hành 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 một trình bao. Nếu không có shell, bạn không thể mở rộng shell của 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à các hàm của shell.
Máy tính này có một hàm shell được định nghĩa là words-only
. Điều này chỉ tính các từ trong một tệp.
function words-only () { wc -w $1 }
Một hàm kỳ lạ có lẽ, “chỉ từ” lâu hơn để nhập so với “wc -w” nhưng ít nhất nó 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 tôi có thể kiểm tra những gì nó hoạt động như thế này:
words-only user_commands.pages
Điều đó hoạt động tốt với một 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 cách sử dụng find
‘S -exec
tùy chọn, nó sẽ không thành công.
find . -name "*.page" -type f -exec words-only "{}" ;
Các find
lệnh 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ể có find
khởi chạy trình bao Bash và chuyển phần còn lại của dòng lệnh cho nó làm đối số cho trình bao. Chúng ta cần đặt 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 “{}
”Thay thế chuỗi.
Trước khi chúng tôi có thể chạy find
chúng ta cần xuất hàm shell của mình với -f
(như một chức năng) tùy chọn:
export -f words-only
find . -name "*.page" -type f -exec bash -c "words-only "{}"" ;
Điều này chạy như mong đợi.
Sử dụng tên tệp nhiều hơn một lần
Nếu bạn muốn liên kết một số lệnh với nhau, bạn có thể làm như vậy và bạn có thể sử dụng “{}
”Thay thế chuỗi trong mỗi lệnh.
find . -name "*.page" -type f -exec bash -c "basename "{}" && words-only "{}"" ;
Nếu chúng ta cd
nâng cấp ra khỏi thư mục “trang” và chạy lệnh đó, find
sẽ vẫn khám phá các tệp PAGE vì nó tìm kiếm đệ quy. Tên tệp và đường dẫn được chuyển đến words-only
hoạt động giống như trước đây. Hoàn toàn vì lý do chứng minh việc sử dụng -exec
với hai lệnh, chúng tôi cũng đang gọi basename
lệnh để xem tên của tệp mà không có đường dẫn của nó.
Cả hai basename
lệnh và words-only
hàm shell có các tên tệp được chuyển cho chúng bằng cách sử dụng “{}
”Thay thế chuỗi.
Khóa học cho các khóa học
Có một hình phạt về thời gian và tải CPU cho việc gọi liên tục một lệnh khi bạn có thể gọi nó một lần và chuyển tất cả các tên tệp cho nó trong một lần. Và nếu bạn đang gọi một trình bao mới mỗi lần để khởi chạy lệnh, chi phí đó sẽ trở nên tồi tệ hơn.
Nhưng đôi khi — tùy thuộc vào những gì bạn đang cố gắng đạt được — bạn có thể không có lựa chọn 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 phải 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.