Câu trả lời:
Một cách khác của POSIX:
c=0
for f in *; do
[ -d "$f" ] && continue
{ grep -q string || c=$(($c + 1)); } < "$f"
done
echo "$c"
Bằng cách chuyển hướng nhóm lệnh thay vì grep
một mình, chúng tôi tránh tính là 1 tệp mà chúng tôi không thể mở (như các tệp mà chúng tôi không có quyền đọc hoặc *
nếu không có tệp không bị ẩn trong thư mục hiện tại).
Với GNU grep
, tương đương sẽ là:
grep -d skip -L foo ./* | grep -c /
Lưu ý rằng bạn không thể sử dụng wc -l
vì tên tệp có thể được tạo thành từ nhiều dòng. Có ./
cũng tránh vấn đề với tên tập tin bắt đầu bằng -
hoặc là -
(mà --
không làm việc xung quanh). Lưu ý rằng nó bỏ qua các tập tin dấu chấm.
Đây là một cách tuân thủ POSIX, trong trường hợp bạn không có grep -L
:
for file in *; do
awk '/string/ { found=1; exit } END{ if(!found) { printf "x" } }' < "$file"
done | wc -c
Tùy thuộc vào số lượng tệp bạn muốn tìm kiếm, đó là một lời khuyên tốt để xem ack-grep . Lý do, vì ack-grep
nhanh hơn rất nhiều so với good'ol grep
và CLI gần như giống hệt nhau.
ack-grep -Lur "some string" * | wc -l
Với zsh
:
( arr=(./*(.N^e_'grep -q PATTERN $REPLY'_)); print ${#arr}; )
Điều này sẽ lưu tên của các tệp không chứa PATTERN
trong một mảng và trả về số lượng phần tử trong mảng. Nó sử dụng vòng loại toàn cầu : .
chỉ chọn các tệp thông thường (thêm D
để bao gồm các tệp ẩn), N
bật null glob
và chuỗi phủ định ( ^
) e
: ^e_'grep -q PATTERN $REPLY'_
tiếp tục bỏ chọn các tên tệp mà mã shell giữa các dấu ngoặc kép trả về true
.
set -- *
, sử dụng$#
và lặp vớifor i do ...
. Bạn không thể sử dụngwc -l
để đếm các tệp vì tên tệp có thể được tạo thành từ nhiều dòng.