Tôi không chắc:
grep -r -i 'the brown dog' /*
thực sự là những gì bạn có ý nghĩa. Điều đó có nghĩa là grep đệ quy trong tất cả các tệp và thư mục không bị ẩn trong /
(nhưng vẫn nhìn vào bên trong các tệp và thư mục ẩn bên trong các tệp đó).
Giả sử bạn có nghĩa là:
grep -r -i 'the brown dog' /
Một số điều cần lưu ý:
- Không phải tất cả các
grep
hỗ trợ thực hiện -r
. Và trong số những hành động đó, các hành vi khác nhau: một số theo các liên kết tượng trưng đến các thư mục khi duyệt qua cây thư mục (có nghĩa là bạn có thể sẽ tìm kiếm nhiều lần trong cùng một tệp hoặc thậm chí chạy trong các vòng lặp vô hạn), một số thì không. Một số sẽ nhìn vào bên trong các tệp thiết bị ( /dev/zero
ví dụ như sẽ mất khá nhiều thời gian ) hoặc các đường ống hoặc tệp nhị phân ..., một số thì không.
- Nó hiệu quả khi
grep
bắt đầu tìm kiếm bên trong các tập tin ngay khi phát hiện ra chúng. Nhưng trong khi nó tìm trong một tệp, nó không còn tìm kiếm thêm tệp để tìm kiếm nữa (có lẽ cũng giống như vậy trong hầu hết các trường hợp)
Của bạn:
find / -type f -exec grep -i 'the brown dog' {} \;
(loại bỏ -r
cái không có ý nghĩa ở đây) là không hiệu quả khủng khiếp vì bạn đang chạy một grep
tệp cho mỗi tệp. ;
chỉ nên được sử dụng cho các lệnh chỉ chấp nhận một đối số. Hơn nữa, ở đây, vì grep
chỉ nhìn trong một tệp, nó sẽ không in tên tệp, vì vậy bạn sẽ không biết các kết quả khớp ở đâu.
Bạn không tìm kiếm bên trong các tập tin thiết bị, đường ống, liên kết tượng trưng ..., bạn không theo dõi các liên kết tượng trưng, nhưng bạn vẫn có khả năng nhìn vào bên trong những thứ như /proc/mem
.
find / -type f -exec grep -i 'the brown dog' {} +
sẽ tốt hơn rất nhiều vì càng ít grep
lệnh càng tốt sẽ được chạy. Bạn sẽ nhận được tên tệp trừ khi lần chạy cuối cùng chỉ có một tệp. Vì vậy, tốt hơn là sử dụng:
find / -type f -exec grep -i 'the brown dog' /dev/null {} +
hoặc với GNU grep
:
find / -type f -exec grep -Hi 'the brown dog' {} +
Lưu ý rằng grep
sẽ không được bắt đầu cho đến khi find
tìm thấy đủ các tệp để nó nhai, do đó sẽ có một số độ trễ ban đầu. Và find
sẽ không tiếp tục tìm kiếm thêm tập tin cho đến khi trước đó grep
đã trở lại. Phân bổ và chuyển danh sách tệp lớn có một số tác động (có thể không đáng kể), do đó, tất cả có lẽ sẽ kém hiệu quả hơn so với grep -r
việc không theo liên kết tượng trưng hoặc nhìn vào bên trong thiết bị.
Với các công cụ GNU:
find / -type f -print0 | xargs -r0 grep -Hi 'the brown dog'
Như trên, càng ít grep
trường hợp càng tốt sẽ được chạy, nhưng find
sẽ tiếp tục tìm kiếm nhiều tệp hơn trong khi lệnh đầu tiên grep
được tìm trong lô đầu tiên. Điều đó có thể hoặc không thể là một lợi thế mặc dù. Chẳng hạn, với dữ liệu được lưu trữ trên các ổ cứng quay find
và việc grep
truy cập dữ liệu được lưu trữ tại các vị trí khác nhau trên đĩa sẽ làm chậm thông lượng đĩa bằng cách làm cho đầu đĩa di chuyển liên tục. Trong thiết lập RAID (nơi find
và grep
có thể truy cập các đĩa khác nhau) hoặc trên SSD, điều đó có thể tạo ra sự khác biệt tích cực.
Trong thiết lập RAID, chạy một số lệnh đồng thời grep
cũng có thể cải thiện mọi thứ. Vẫn với các công cụ GNU trên bộ lưu trữ RAID1 với 3 đĩa,
find / -type f -print0 | xargs -r0 -P2 grep -Hi 'the brown dog'
có thể tăng hiệu suất đáng kể. Tuy nhiên, lưu ý rằng cái thứ hai grep
sẽ chỉ được bắt đầu khi đã tìm thấy đủ các tệp để điền vào grep
lệnh đầu tiên . Bạn có thể thêm một -n
tùy chọn để xargs
điều đó xảy ra sớm hơn (và truyền ít tệp hơn cho mỗi lần grep
gọi).
Cũng lưu ý rằng nếu bạn đang chuyển hướng xargs
đầu ra sang bất cứ thứ gì ngoại trừ thiết bị đầu cuối, thì greps
s sẽ bắt đầu đệm đầu ra của chúng, điều đó có nghĩa là đầu ra của những cái đó grep
có thể sẽ bị xen kẽ không chính xác. Bạn sẽ phải sử dụng stdbuf -oL
(nếu có sẵn như trên GNU hoặc FreeBSD) để giải quyết vấn đề đó (bạn vẫn có thể gặp vấn đề với các dòng rất dài (thường> 4KiB)) hoặc mỗi lần ghi đầu ra của chúng vào một tệp riêng biệt và ghép chúng lại tất cả cuối cùng
Ở đây, chuỗi bạn đang tìm kiếm đã được sửa chữa (không phải là biểu thức chính quy) vì vậy sử dụng -F
tùy chọn này có thể tạo ra sự khác biệt (không chắc vì các grep
triển khai đã biết cách tối ưu hóa điều đó rồi).
Một điều khác có thể tạo ra sự khác biệt lớn là sửa lỗi miền địa phương thành C nếu bạn ở miền địa phương nhiều byte:
find / -type f -print0 | LC_ALL=C xargs -r0 -P2 grep -Hi 'the brown dog'
Để tránh nhìn vào bên trong /proc
, /sys
..., hãy sử dụng -xdev
và chỉ định hệ thống tệp bạn muốn tìm kiếm trong:
LC_ALL=C find / /home -xdev -type f -exec grep -i 'the brown dog' /dev/null {} +
Hoặc cắt tỉa các đường dẫn bạn muốn loại trừ một cách rõ ràng:
LC_ALL=C find / \( -path /dev -o -path /proc -o -path /sys \) -prune -o \
-type f -exec grep -i 'the brown dog' /dev/null {} +