Tôi đang làm một findvà sau đó nhận được một danh sách các tập tin. Làm thế nào để tôi chuyển nó sang một tiện ích khác như cat(để con mèo hiển thị nội dung của tất cả các tệp đó) và về cơ bản cần grepmột cái gì đó từ các tệp này.
Tôi đang làm một findvà sau đó nhận được một danh sách các tập tin. Làm thế nào để tôi chuyển nó sang một tiện ích khác như cat(để con mèo hiển thị nội dung của tất cả các tệp đó) và về cơ bản cần grepmột cái gì đó từ các tệp này.
Câu trả lời:
Chuyển sang quy trình khác (Mặc dù điều này sẽ không hoàn thành những gì bạn nói bạn đang cố gắng thực hiện):
command1 | command2
Điều này sẽ gửi đầu ra của lệnh1 là đầu vào của lệnh2
-exectrên một find(điều này sẽ làm những gì bạn muốn làm - nhưng cụ thể là find)
find . -name '*.foo' -exec cat {} \;
(Tất cả mọi thứ giữa findvà -execlà các biến vị ngữ tìm kiếm mà bạn đã sử dụng. {}Sẽ thay thế tệp cụ thể mà bạn tìm thấy trong lệnh ( cat {}trong trường hợp này); \;là kết thúc -execlệnh.)
gửi đầu ra của một tiến trình dưới dạng đối số dòng lệnh đến tiến trình khác
command2 `command1`
ví dụ:
cat `find . -name '*.foo' -print`
(Lưu ý đây là BACK-QUOTES không phải là trích dẫn thông thường (dưới dấu ngã ~ trên bàn phím của tôi).) Điều này sẽ gửi đầu ra command1thành các command2đối số dòng lệnh. Lưu ý rằng tên tệp chứa khoảng trắng (dòng mới, v.v.) sẽ được chia thành các đối số riêng biệt.
findcho phép bạn viết : find . -name '*.foo' -exec cat {} +, trong đó +chỉ ra rằng findnên nhóm nhiều tên tệp thuận tiện thành một lệnh gọi duy nhất. Điều này khá hữu ích (nó xử lý các khoảng trắng vv trong tên tệp mà không cần dùng đến -print0và xargs -0).
find . -name '*.foo' | xargs cat
find . -name '*.foo' | xargs cat | grep string
POSIX 2008 đã thêm +điểm đánh dấu vào findđó có nghĩa là nó tự động nhóm nhiều tệp hợp lý thành một lệnh thực thi, rất giống như xargsvậy, nhưng với một số lợi thế:
Vấn đề tên tệp là vấn đề xargskhông có -0tùy chọn và vấn đề 'chạy ngay cả với tên tệp không' là vấn đề có hoặc không có -0tùy chọn - nhưng GNU xargscó -rhoặc --no-run-if-emptytùy chọn để ngăn điều đó xảy ra. Ngoài ra, ký hiệu này cắt giảm số lượng quy trình, không phải là bạn có khả năng đo lường sự khác biệt về hiệu suất. Do đó, bạn có thể viết một cách hợp lý:
find . -exec grep something {} +
find . -print | xargs grep something
Nếu bạn đang dùng Linux hoặc có GNU findvà xargscác lệnh, thì hãy sử dụng -print0vớifind và -0với xargsđể xử lý các tên tệp có chứa khoảng trắng và các ký tự bóng lẻ khác.
find . -print0 | xargs -0 grep something
grepNếu bạn không muốn tên tệp (chỉ là văn bản) thì hãy thêm một tùy chọn thích hợp vào grep(thường là -hđể loại bỏ 'tiêu đề'). Để đảm bảo tuyệt đối tên tệp được in bởi grep(ngay cả khi chỉ tìm thấy một tệp hoặc lệnh gọi cuối cùng grepchỉ được cung cấp 1 tên tệp), sau đó thêm /dev/nullvào xargsdòng lệnh, để luôn có ít nhất hai tên tệp.
xargs grep something.
findđược dẫn đến đầu vào tiêu chuẩn của xargs. Các xargschương trình đọc đầu vào tiêu chuẩn của nó, tách đầu vào lúc khoảng trắng (khoảng trống, dòng mới, các tab, vv) và gắn thêm một số các từ với lệnh grep somethingvà thực thi dòng lệnh. xargssau đó tiếp tục đọc các lệnh đầu vào và thực thi cho đến khi hết đầu vào. xargschạy greplệnh thường xuyên khi cần thiết cho đầu vào được đưa ra (từ findtrong ví dụ này).
/dev/nullmất các thông báo lỗi.
Có một số cách để chuyển danh sách các tệp được findlệnh trả về cho catlệnh, mặc dù về mặt kỹ thuật không phải tất cả đều sử dụng đường ống và không có đường dẫn nào thực sự dẫn trực tiếp đến cat.
Đơn giản nhất là sử dụng backticks ( `):
cat `find [whatever]`
Điều này nhận đầu ra findvà đặt nó một cách hiệu quả trên dòng lệnh của cat. Điều này không hoạt động tốt nếu findcó quá nhiều đầu ra (nhiều hơn có thể vừa với một dòng lệnh) hoặc nếu đầu ra có các ký tự đặc biệt (như khoảng trắng).
Trong một số shell, bao gồm bash, người ta có thể sử dụng $()thay vì backticks:
cat $(find [whatever])
Điều này là ít di động, nhưng là lồng nhau. Bên cạnh đó, nó có khá nhiều cảnh báo tương tự như backticks.
Bởi vì chạy các lệnh khác trên những gì được tìm thấy là sử dụng phổ biến cho find, find có một -exechành động thực thi một lệnh cho mỗi tệp mà nó tìm thấy:
find [whatever] -exec cat {} \;
Đây {}là một trình giữ chỗ cho tên tệp và \;đánh dấu sự kết thúc của lệnh (Có thể có các hành động khác sau -exec.)
Điều này sẽ chạy catmột lần cho mỗi tệp duy nhất thay vì chạy một trường hợp cattruyền cho nó nhiều tên tệp có thể không hiệu quả và có thể không có hành vi bạn muốn cho một số lệnh (mặc dù điều đó tốt cat). Cú pháp cũng khó gõ - bạn cần thoát dấu chấm phẩy vì dấu chấm phẩy đặc biệt đối với shell!
Một số phiên bản find(đáng chú ý nhất là phiên bản GNU) cho phép bạn thay thế ;bằng +để sử dụng -execchế độ chắp thêm để chạy ít phiên bản cat:
find [whatever] -exec cat {} +
Điều này sẽ chuyển nhiều tên tệp cho mỗi lần gọi cat, có thể hiệu quả hơn.
Lưu ý rằng điều này không được đảm bảo để sử dụng một lệnh gọi, tuy nhiên. Nếu dòng lệnh sẽ quá dài thì các đối số được trải rộng trên nhiều lệnh cat. Đối với catđiều này có lẽ không phải là một vấn đề lớn, nhưng đối với một số lệnh khác, điều này có thể thay đổi hành vi theo những cách không mong muốn. Trên các hệ thống Linux, giới hạn độ dài dòng lệnh là khá lớn, do đó việc chia thành nhiều lệnh gọi là khá hiếm so với một số HĐH khác.
Phương pháp cổ điển / di động là sử dụng xargs:
find [whatever] | xargs cat
xargschạy lệnh được chỉ định ( cat, trong trường hợp này) và thêm các đối số dựa trên những gì nó đọc từ stdin. Cũng giống như -execvới +, điều này sẽ phá vỡ dòng lệnh nếu cần thiết. Đó là, nếu findtạo ra quá nhiều đầu ra, nó sẽ chạy catnhiều lần. Như đã đề cập trong phần về -exectrước đó, có một số lệnh trong đó việc chia tách này có thể dẫn đến hành vi khác nhau. Lưu ý rằng việc sử dụng xargsnhư thế này có vấn đề với khoảng trắng trong tên tệp, vì xargschỉ sử dụng khoảng trắng làm dấu phân cách.
Phương pháp mạnh mẽ, di động và hiệu quả nhất cũng sử dụng xargs:
find [whatever] -print0 | xargs -0 cat
Các -print0lá cờ nói findđể sử dụng \0(null ký tự) delimiters giữa tên tập tin, và các -0lá cờ nói xargsđể mong đợi những \0dấu phân cách. Điều này có khá nhiều hành vi giống hệt với -exec... +cách tiếp cận, mặc dù có tính di động cao hơn (nhưng không may là dài dòng hơn).
ls.
$()Cũng hoạt động với các lệnh khác find .
Nghe có vẻ như một công việc cho một kịch bản shell đối với tôi:
for file in 'find -name *.xml'
do
grep 'hello' file
done
hoặc điều tương tự
Lệnh find có một đối số -exec mà bạn có thể sử dụng cho những thứ như thế này, bạn chỉ có thể thực hiện grep trực tiếp bằng cách sử dụng.
Ví dụ ( từ đây, các ví dụ hay khác tại trang này ):
find . -exec grep "www.athabasca" '{}' \; -print
Trong bash, những điều sau đây sẽ phù hợp:
find /dir -type f -print0 | xargs -0i cat {} | grep whatever
Điều này sẽ tìm thấy tất cả các tập tin trong /dirthư mục, và đưa tên tập tin vào xargsmột cách an toàn grep.
Bỏ qua xargskhông phải là một ý tưởng tốt nếu bạn có nhiều ngàn tệp trong đó /dir; catsẽ phá vỡ do độ dài danh sách đối số quá mức. xargssẽ sắp xếp tất cả ra cho bạn
Đối -print0số để chia findlưới với -0đối số xargsđể xử lý tên tệp có khoảng trắng đúng. Đối -isố xargscho phép bạn chèn tên tệp khi cần trong catdòng lệnh. Các dấu ngoặc được thay thế bằng tên tệp được dẫn vào catlệnh từ find.
Điều này làm việc cho tôi
find _CACHE_* | while read line; do
cat "$line" | grep "something"
done
Điều này sẽ in tên và nội dung của các tệp chỉ đệ quy ..
find . -type f -printf '\n\n%p:\n' -exec cat {} \;
Chỉnh sửa (Phiên bản cải tiến): Điều này sẽ in tên và nội dung của tệp văn bản (ascii) chỉ đệ quy ..
find . -type f -exec grep -Iq . {} \; -print | xargs awk 'FNR==1{print FILENAME ":" $0; }'
Thêm một lần thử
find . -type f -exec grep -Iq . {} \; -printf "\n%p:" -exec cat {} \;
Bạn đang cố gắng tìm văn bản trong các tập tin? Bạn chỉ có thể sử dụng grep cho ...
grep searchterm *
Để liệt kê và xem nội dung của tất cả các tệp abc.def trên máy chủ trong thư mục / ghi và / jkl
find /ghi /jkl -type f -name abc.def 2> /dev/null -exec ls {} \; -exec cat {} \;
Để liệt kê các tệp abc.def có các mục nhận xét và hiển thị, hãy xem các mục đó trong thư mục / ghi và / jkl
find /ghi /jkl -type f -name abc.def 2> /dev/null -exec grep -H ^# {} \;
find -name '*.foo' -printđã làm việc rất tốt cho tôi ... Cảm ơn