Lưu ý:
* Câu trả lời này có thể đi sâu hơn các bảo đảm trường hợp sử dụng và find 2>/dev/null
có thể đủ tốt trong nhiều tình huống. Nó vẫn có thể được quan tâm cho một viễn cảnh đa nền tảng và thảo luận về một số kỹ thuật vỏ tiên tiến nhằm tìm kiếm một giải pháp mạnh mẽ nhất có thể, mặc dù các trường hợp được bảo vệ chống lại phần lớn là giả thuyết.
* Nếu hệ thống của bạn được định cấu hình để hiển thị các thông báo lỗi cục bộ , hãy thêm tiền tố vào các find
cuộc gọi bên dưới bằng LC_ALL=C
( LC_ALL=C find ...
) để đảm bảo rằng các thông báo tiếng Anh được báo cáo, để nó grep -v 'Permission denied'
hoạt động như dự định. Tuy nhiên, bất kỳ lúc nào, bất kỳ thông báo lỗi nào được hiển thị cũng sẽ bằng tiếng Anh.
Nếu trình baobash
zsh
của bạn là hoặc , có một giải pháp mạnh mẽ trong khi đơn giản một cách hợp lý , chỉfind
sử dụng các tính năng tuân thủ POSIX ; trong khi bash
bản thân nó không phải là một phần của POSIX, hầu hết các nền tảng Unix hiện đại đều đi kèm với nó, làm cho giải pháp này có thể mang theo rộng rãi:
find . > files_and_folders 2> >(grep -v 'Permission denied' >&2)
Lưu ý: Có một cơ hội nhỏ rằng một số grep
đầu ra có thể đến sau khi find
hoàn thành, bởi vì lệnh tổng thể không đợi lệnh bên trong >(...)
kết thúc. Trong bash
, bạn có thể ngăn chặn điều này bằng cách thêm | cat
vào lệnh.
>(...)
là một (hiếm khi được sử dụng) đầu ra quá trình thay thế mà cho phép chuyển hướng đầu ra (trong trường hợp này, stderr đầu ra ( 2>
) cho stdin của bên lệnh >(...)
.
Ngoài bash
và zsh
, ksh
hỗ trợ họ cũng về nguyên tắc , nhưng cố gắng để kết hợp chúng với chuyển hướng từ stderr , như được thực hiện ở đây ( 2> >(...)
), dường như bị bỏ qua âm thầm (trong ksh 93u+
).
grep -v 'Permission denied'
lọc ra ( -v
) tất cả các dòng (từ find
luồng stderr của lệnh) có chứa cụm từ Permission denied
và xuất các dòng còn lại thành stderr ( >&2
).
Cách tiếp cận này là:
mạnh mẽ : grep
chỉ được áp dụng cho các thông báo lỗi (và không phải là sự kết hợp của các đường dẫn tệp và thông báo lỗi, có khả năng dẫn đến dương tính giả) và các thông báo lỗi không phải là thông báo bị từ chối cấp phép được chuyển qua stderr.
side-effect free : find
mã thoát của mã được giữ nguyên: không thể truy cập ít nhất một trong các mục hệ thống tệp gặp phải kết quả trong mã thoát 1
(mặc dù điều đó sẽ không cho bạn biết liệu có xảy ra lỗi nào ngoài các lỗi bị từ chối cấp phép hay không).
Các giải pháp tuân thủ POSIX:
Các giải pháp hoàn toàn tuân thủ POSIX có những hạn chế hoặc yêu cầu công việc bổ sung.
Nếu find
's đầu ra là để được chụp trong một tập tin nào (hoặc bị ức chế hoàn toàn), sau đó là giải pháp đường ống dựa trên từ câu trả lời Jonathan Leffler của rất đơn giản, mạnh mẽ, và POSIX-compliant:
find . 2>&1 >files_and_folders | grep -v 'Permission denied' >&2
Lưu ý rằng thứ tự của các chuyển hướng có vấn đề: 2>&1
phải đến trước .
Việc bắt đầu ra thiết bị xuất chuẩn trong một tệp ở phía trước cho phép chỉ2>&1
gửi các thông báo lỗi thông qua đường ống, sau đó có thể hoạt động rõ ràng trên đó.grep
Các Nhược điểm duy nhất là các mã thoát tổng thể sẽ là grep
của lệnh , chứ không phải find
's, mà trong trường hợp này có nghĩa là: nếu có không có lỗi nào cả hoặc chỉ lỗi phép-bị từ chối, mã lối ra sẽ được 1
(tín hiệu thất bại ), nếu không ( lỗi khác với những người bị từ chối cấp phép) 0
- đó là điều ngược lại với ý định.
Điều đó nói rằng, find
mã thoát hiếm khi được sử dụng dù sao đi nữa , vì nó thường truyền tải ít thông tin ngoài sự thất bại cơ bản như đi qua một con đường không tồn tại.
Tuy nhiên, trường hợp cụ thể thậm chí chỉ một sốcủa các đường dẫn đầu vào không thể truy cập do thiếu quyền được phản ánh trong find
mã thoát (trong cả GNU và BSD find
): nếu xảy ra lỗi từ chối quyền đối với bất kỳ tệp nào được xử lý, mã thoát được đặt thành 1
.
Các biến thể sau đây giải quyết rằng:
find . 2>&1 >files_and_folders | { grep -v 'Permission denied' >&2; [ $? -eq 1 ]; }
Bây giờ, mã thoát cho biết liệu có bất kỳ lỗi nào khác Permission denied
xảy ra hay không: 1
nếu 0
có thì ngược lại.
Nói cách khác: mã thoát bây giờ phản ánh ý định thực sự của lệnh: thành công ( 0
) được báo cáo, nếu không có lỗi nào hoặc chỉ xảy ra lỗi từ chối cấp phép.
Điều này được cho là thậm chí còn tốt hơn là chỉ truyền find
mã thoát ra, như trong giải pháp ở trên cùng.
gniourf_gniourf trong các bình luận đề xuất khái quát hóa (vẫn tuân thủ POSIX) của giải pháp này bằng cách sử dụng các chuyển hướng tinh vi , hoạt động ngay cả với hành vi mặc định của việc in các đường dẫn tệp tới thiết bị xuất chuẩn :
{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1
Nói tóm lại: Tuỳ chỉnh tập tin mô tả 3
được sử dụng để tạm thời trao đổi stdout ( 1
) và stderr ( 2
), do đó các thông báo lỗi một mình có thể được đường ống để grep
qua stdout.
Nếu không có các chuyển hướng này, cả dữ liệu (đường dẫn tệp) và thông báo lỗi sẽ được chuyển grep
qua thiết bị xuất chuẩn và grep
sau đó không thể phân biệt giữa thông báo lỗi Permission denied
và tệp (giả định) có tên xảy ra để chứa cụm từ Permission denied
.
Tuy nhiên, như trong giải pháp đầu tiên, mã thoát được báo cáo sẽ là grep
, không phải find
, nhưng có thể áp dụng cách khắc phục tương tự như trên.
Ghi chú về các câu trả lời hiện có:
Có một số điểm cần lưu ý về câu trả lời của Michael Brux , find . ! -readable -prune -o -print
:
Nó đòi hỏi GNU find
; Đáng chú ý, nó sẽ không hoạt động trên macOS. Tất nhiên, nếu bạn chỉ cần lệnh để làm việc với GNU find
, thì đây sẽ không phải là vấn đề đối với bạn.
Một số Permission denied
lỗi vẫn có thể xuất hiện : find ! -readable -prune
báo cáo các lỗi như vậy cho các mục con của thư mục mà người dùng hiện tại có r
quyền, nhưng thiếu quyền x
(thực thi). Lý do là vì các thư mục riêng của mình là có thể đọc được, -prune
không được thực hiện, và những nỗ lực đi xuống vào thư mục đó sau đó kích hoạt các thông báo lỗi. Điều đó nói rằng, trường hợp điển hình là cho r
phép mất tích.
Lưu ý: Điểm sau đây là vấn đề triết lý và / hoặc trường hợp sử dụng cụ thể và bạn có thể quyết định nó không phù hợp với bạn và lệnh đó phù hợp với nhu cầu của bạn, đặc biệt nếu chỉ cần in các đường dẫn là tất cả những gì bạn làm:
- Nếu bạn khái niệm hóa việc lọc các thông báo lỗi bị từ chối cấp phép một tác vụ riêng mà bạn muốn có thể áp dụng cho bất kỳ
find
lệnh nào , thì cách tiếp cận ngược lại của việc chủ động ngăn chặn các lỗi bị từ chối cấp phép yêu cầu đưa "nhiễu" vào find
lệnh, cũng giới thiệu phức tạp và cạm bẫy logic .
- Chẳng hạn, bình luận được bình chọn nhiều nhất về câu trả lời của Michael (khi viết bài này) cố gắng chỉ ra cách mở rộng lệnh bằng cách bao gồm
-name
bộ lọc, như sau:
find . ! -readable -prune -o -name '*.txt'
Tuy nhiên, điều này không hoạt động như dự định, vì -print
hành động theo dõi là bắt buộc (một lời giải thích có thể được tìm thấy trong câu trả lời này ). Sự tinh tế như vậy có thể giới thiệu lỗi.
Giải pháp đầu tiên trong câu trả lời của Jonathan Leffler của , find . 2>/dev/null > files_and_folders
, như chính Người đã khẳng định, một cách mù quáng im lặng tất cả các thông báo lỗi (và các cách giải quyết là cồng kềnh và không hoàn toàn mạnh mẽ, như ông cũng giải thích). Tuy nhiên, nói một cách thực tế , đó là giải pháp đơn giản nhất , vì bạn có thể hài lòng khi cho rằng bất kỳ và tất cả các lỗi sẽ liên quan đến sự cho phép.
câu trả lời sương của , sudo find . > files_and_folders
, ngắn gọn và thực dụng, nhưng rất thiếu khôn ngoan cho bất cứ điều gì khác hơn là chỉ đơn thuần là in tên tập tin , vì lý do an ninh: bởi vì bạn đang chạy là gốc người dùng, "bạn có nguy cơ có toàn bộ hệ thống của bạn bị messed up bởi một lỗi trong tìm hoặc một phiên bản độc hại, hoặc một lời mời không chính xác viết một cái gì đó bất ngờ, điều đó không thể xảy ra nếu bạn chạy nó với các đặc quyền bình thường "(từ một nhận xét về câu trả lời của sương mù bởi tripleee ).
Giải pháp thứ 2 trong câu trả lời của viraptor , find . 2>&1 | grep -v 'Permission denied' > some_file
có nguy cơ dương tính giả (do gửi hỗn hợp stdout và stderr qua đường ống), và, có khả năng, thay vì báo cáo các lỗi không thể từ chối thông qua stderr, bắt chúng dọc theo đường dẫn đầu ra trong tập tin đầu ra.
find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2
?