Làm cách nào tôi có thể loại trừ tất cả các quyền của từ chối từ chối tin nhắn của người dùng từ thành viên tìm thấy trên mạng?


794

Tôi cần ẩn tất cả các tin nhắn bị từ chối cấp phép khỏi:

find . > files_and_folders

Tôi đang thử nghiệm khi tin nhắn như vậy phát sinh. Tôi cần phải thu thập tất cả các thư mục và tập tin mà nó không phát sinh.

Có thể chỉ đạo các cấp phép cho files_and_folderstập tin?

Làm thế nào tôi có thể ẩn các lỗi cùng một lúc?

Câu trả lời:


259

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/nullcó 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 findcuộ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 baobashzsh của bạn 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 bashbả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 | catvà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 bashzsh, kshhỗ 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ừ findluồng stderr của lệnh) có chứa cụm từ Permission deniedvà 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ẽ : grepchỉ đượ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 : findmã 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>&1phả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à grepcủ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, findmã 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 findmã 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: 1nếu 0có 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 findmã 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 để grepqua stdout.

Nếu không có các chuyển hướng này, cả dữ liệu (đường dẫn tệp) thông báo lỗi sẽ được chuyển grepqua thiết bị xuất chuẩn và grepsau đó không thể phân biệt giữa thông báo lỗi Permission deniedtệ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 deniedlỗi vẫn có thể xuất hiện : find ! -readable -prunebá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ó rquyề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 có thể đọc được, -prunekhô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 rphé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 findlệ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 -namebộ 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ì -printhà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_filecó 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.


4
Chỉ cần một câu hỏi nhanh: tại sao bạn sử dụng một sự thay thế quá trình mà không chỉ là một đường ống : find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2?
gniourf_gniourf

2
@ LéoLéopoldHertz: Nếu bạn không muốn xuất ra một tệp bên ngoài, chỉ cần thực hiện thêm hệ thống ống nước:{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1
gniourf_gniourf

2
@ LéoLéopoldHertz: Chỉ là nó tuân thủ POSIX. Quá trình thay thế >(...)là đặc thù của Bash.
gniourf_gniourf

2
Tôi không chắc chắn rằng việc giữ nguyên mã thoát findphải được nhấn mạnh và quảng cáo: findmã thoát là vô dụng. Ở đây, nó rất có thể sẽ khác không (và vô dụng như vậy).
gniourf_gniourf

3
POSIX rõ ràng yêu cầu execute/searchquyền của chế độ tệp để 'tìm kiếm' một thư mục (truy xuất các nút của các tệp được chứa). findthực hiện điều này để đi xuống thư mục con (ngoài việc yêu cầu readquyền liệt kê các tệp trong một thư mục). Đây không phải là 'lỗi' hoặc 'lỗi chuyển'.
wjordan

542

Sử dụng:

find . 2>/dev/null > files_and_folders

Điều này ẩn không chỉ các Permission deniedlỗi, tất nhiên, nhưng tất cả các thông báo lỗi.

Nếu bạn thực sự muốn giữ các lỗi có thể khác, chẳng hạn như có quá nhiều bước nhảy trên một liên kết tượng trưng, ​​nhưng không phải là quyền bị từ chối, thì có lẽ bạn phải đoán rằng bạn không có nhiều tệp gọi là 'quyền bị từ chối' và cố gắng:

find . 2>&1 | grep -v 'Permission denied' > files_and_folders

Nếu bạn thực sự muốn lọc chỉ lỗi tiêu chuẩn, bạn có thể sử dụng cấu trúc phức tạp hơn:

find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2

Chuyển hướng I / O trên findlệnh là : 2>&1 > files_and_folders |. Ống chuyển hướng đầu ra tiêu chuẩn cho greplệnh và được áp dụng đầu tiên. Các 2>&1gửi sai số chuẩn để cùng một vị trí như đầu ra tiêu chuẩn (ống). Đầu ra > files_and_foldersgửi tiêu chuẩn (nhưng không phải lỗi tiêu chuẩn) đến một tệp. Kết quả cuối cùng là các thông báo được ghi vào lỗi tiêu chuẩn được gửi xuống đường ống và đầu ra thông thường findđược ghi vào tệp. Các grepbộ lọc đầu ra tiêu chuẩn (bạn có thể quyết định mức độ chọn lọc của mình và có thể phải thay đổi chính tả tùy thuộc vào ngôn ngữ và O / S) và cuối cùng>&2có nghĩa là các thông báo lỗi còn tồn tại (được ghi vào đầu ra tiêu chuẩn) lại chuyển sang lỗi tiêu chuẩn. Chuyển hướng cuối cùng có thể được coi là tùy chọn tại thiết bị đầu cuối, nhưng sẽ là một ý tưởng rất tốt để sử dụng nó trong một tập lệnh để thông báo lỗi xuất hiện trên lỗi tiêu chuẩn.

Có những biến thể vô tận về chủ đề này, tùy thuộc vào những gì bạn muốn làm. Điều này sẽ hoạt động trên mọi biến thể của Unix với bất kỳ dẫn xuất shell Bourne nào (Bash, Korn, Nhận) và bất kỳ phiên bản nào tuân thủ POSIX của find.

Nếu bạn muốn thích ứng với phiên bản cụ thể của findbạn có trên hệ thống của mình, có thể có các tùy chọn thay thế khả dụng. GNU findnói riêng có vô số tùy chọn không có sẵn trong các phiên bản khác - xem câu trả lời hiện được chấp nhận cho một bộ tùy chọn như vậy.


9
Nếu bạn giống như tôi, chú ý rằng thiếu không gian là quan trọng! 2>/dev/null, không có không gian!
Nik

20
Đây 2>là một đơn vị không có bất kỳ không gian; bạn có thể có một khoảng trắng giữa nó và tên tệp. Tương tự với các chuyển hướng khác, chẳng hạn như 2>&1(chuyển hướng lỗi tiêu chuẩn đến cùng một nơi với đầu ra tiêu chuẩn đang diễn ra) hoặc 2>&-đóng lỗi tiêu chuẩn, v.v. Xem phần Chuyển hướng để biết chi tiết tin đồn còn lại. (Mã ở trên là vỏ giống như POSIX, không cụ thể bash.)
Jonathan Leffler

3
Tôi đã phải sử dụng vốn P vì đó là những gì thiết bị đầu cuối của tôi sẽ xuất ra: tìm. 2> & 1 | grep -v 'Quyền bị từ chối'
David Doria

4
Làm thế nào đây là một giải pháp chấp nhận được? 1) Bạn đang chuyển hướng TẤT CẢ lỗi thành dev / null 2) Bạn đang lọc một chuỗi lỗi rõ ràng !! Tùy thuộc vào những điều này là dễ vỡ và điều gì xảy ra nếu tệp của bạn nằm trong một thư mục có tên 'quyền bị từ chối'? Giáo sư!
Gunchars

10
Tôi phản đối việc grepping chuỗi lỗi để sửa đổi đầu ra của chương trình. Nó sẽ hoạt động hầu hết thời gian, nhưng đơn giản không phải là giải pháp chính xác (tìm với perm bên dưới là). Để cho bạn một ví dụ tại sao, điều này sẽ không hoạt động trên OSX vì lỗi là "Quyền bị từ chối". Tương tự đối với bất kỳ hệ thống nào khác, nơi có sự khác biệt rất nhỏ trong chuỗi lỗi (quốc tế hóa ai?)
Gunchars

285

Sử dụng:

find . ! -readable -prune -o -print

hay nói chung hơn

find <paths> ! -readable -prune -o <other conditions like -name> -print
  • để tránh "Quyền bị từ chối"
  • VÀ KHÔNG loại bỏ thông báo lỗi (khác)
  • VÀ nhận trạng thái thoát 0 ("tất cả các tệp được xử lý thành công")

Hoạt động với: find (GNU findutils) 4.4.2. Lý lịch:

  • Các -readablethử nghiệm phù hợp với các tập tin có thể đọc được. Các !nhà điều hành trả về true, khi kiểm tra là sai. Và ! -readablephù hợp với các thư mục không thể đọc được (& tập tin).
  • Các -prunehành động không đi vào thư mục.
  • ! -readable -prune có thể được dịch thành: nếu thư mục không thể đọc được, đừng đi xuống.
  • Bài -readablekiểm tra đưa vào danh sách kiểm soát truy cập và các thành phần cấp phép khác mà -permbài kiểm tra bỏ qua.

Xem thêm find(1) manpage để biết thêm chi tiết.


6
sự khác biệt đã được đề cập. Nếu bạn không hiểu, thì câu trả lời có thể không có gì khác biệt đối với bạn? STDOUT giống nhau - STDERR thì khác (bạn nhận được các thông báo lỗi khác với câu trả lời này) - $? là khác nhau (là 0 "thành công" với câu trả lời này, khi không có lỗi nào khác xảy ra - luôn luôn> 0 "không thành công" khi chuyển hướng đến dev / null) - có lẽ ai đó cần "chính xác" $? trong một kịch bản
Michael Brux

6
@Masi lỗ hổng rõ ràng nhất là câu trả lời của Jonathan (grep -v) sẽ loại trừ tên tệp có chứa 'Quyền bị từ chối' :)
Fruit

65
Tôi cảm thấy thích hợp để thêm vào đây rằng nếu bạn cần thêm một số tiêu chí tìm kiếm khác, thì nên thực hiện với -o:find . ! -readable -prune -o -name '*.txt'
tempestadept

22
Lưu ý rằng POSIX findkhông bao gồm -readabledưới dạng tùy chọn; cả findBSD và Mac OS X cũng vậy (tôi không chắc về các hệ thống khác). Vì vậy, nơi bạn có GNU findđược bảo đảm, điều này hoạt động rất tốt, nhưng không rõ ràng làm thế nào để điều chỉnh điều này nếu bạn không thể đảm bảo rằng hệ thống đã findcài đặt GNU . (Nó sẽ hoạt động tốt trên Linux; nó có thể hoạt động ở nơi khác.)
Jonathan Leffler

6
find . ! -readable -prune -o -name '*.txt'dường như không hoạt động trên Ubuntu 14.04 khi sử dụng find 4.2.2. Nó dường như ăn sâu vào -name. Vì một số lý do kỳ lạ, tôi đã thành công vớifind . \( ! -readable -prune \) -o -name '*.txt' -print
con-f-use

110

Nếu bạn muốn bắt đầu tìm kiếm từ root "/", có thể bạn sẽ thấy đầu ra đôi khi như:

find: /./proc/1731/fdinfo: Permission denied
find: /./proc/2032/task/2032/fd: Permission denied

Đó là vì sự cho phép. Để giải quyết điều này:

  1. Bạn có thể sử dụng lệnh sudo:

    sudo find /. -name 'toBeSearched.file'

Nó hỏi mật khẩu siêu người dùng, khi nhập mật khẩu bạn sẽ thấy kết quả bạn thực sự muốn gì. Nếu bạn không có quyền sử dụng lệnh sudo, điều đó có nghĩa là bạn không có mật khẩu siêu người dùng, trước tiên hãy yêu cầu quản trị viên hệ thống thêm bạn vào tệp sudoers.

  1. Bạn có thể sử dụng chuyển hướng Đầu ra lỗi tiêu chuẩn từ (Hiển thị / màn hình chung) sang một số tệp và tránh nhìn thấy các thông báo lỗi trên màn hình! chuyển hướng đến một tập tin đặc biệt / dev / null:

    find /. -name 'toBeSearched.file' 2>/dev/null
  2. Bạn có thể sử dụng chuyển hướng Đầu ra lỗi tiêu chuẩn từ (Hiển thị / màn hình chung) sang đầu ra tiêu chuẩn (Hiển thị / màn hình chung), sau đó chuyển đổi bằng lệnh grep với tham số -v "đảo ngược" để không thấy các dòng đầu ra có 'Quyền bị từ chối' cặp từ:

    find /. -name 'toBeSearched.file' 2>&1 | grep -v 'Permission denied'

7
@scottmrogowski ngoại trừ việc nó không trả lời câu hỏi ... 1. yêu cầu quản trị viên hệ thống thêm bạn vào tệp sudoers. 2.sudo find...
Stephen

1
Chính xác những gì tôi đang tìm kiếm!
DankMasterDan

92

Tôi đã phải sử dụng:

find / -name expect 2>/dev/null

chỉ định tên của những gì tôi muốn tìm và sau đó bảo nó chuyển hướng tất cả các lỗi sang / dev / null

mong đợi là vị trí của chương trình mong đợi mà tôi đang tìm kiếm.


3
@Masi, lệnh trong câu trả lời không sử dụng expect. Thay vào đó, expectchỉ đơn giản là tên của tệp mà lệnh này sẽ cố gắng tìm.
Dhruv Kapoor

2
Chuyển hướng một cách mù quáng tất cả đầu ra stderr chỉ để bỏ qua một lớp thông báo lỗi nói chung là một ý tưởng tồi - bạn sẽ mất tất cả các lỗi tùy ý khác trong quy trình.
Josip Rodin

59

Chuyển stderrsang /dev/nullsử dụng 2> / dev / null

find . -name '...' 2>/dev/null


2
Điều này hoạt động tốt với tôi ngay cả trên Mac OSX. Hoặc thậm chífind . -name '...' -print 2>/dev/null
Shadowheep

30

Bạn cũng có thể sử dụng các vị từ -perm-prunevị từ để tránh đi xuống các thư mục không thể đọc được (xem thêm Làm cách nào để xóa câu lệnh in "quyền bị từ chối" khỏi chương trình tìm kiếm? - Unix & Linux Stack Exchange ):

find . -type d ! -perm -g+r,u+r,o+r -prune -o -print > files_and_folders

4
-perm -g+r,u+r,o+rchỉ khớp với các tệp có quyền r(đọc) được đặt cho cả 3 nguyên tắc bảo mật của tệp , không liên quan trực tiếp đến việc người dùng hiện tại có thể đọc tệp đó hay không. Nó có khả năng bỏ lỡ cả các tệp mà người dùng hiện tại có thể đọc và khớp với các tệp mà họ không thể.
mkuity0

Tôi nghĩ rằng find . -type d ! \( -perm -u+r -o -perm -g+r -o -perm -o+r \) -prune -o -printsẽ là giải pháp tốt.
Mattia72

2
@ Mattia72: Không, nó là cơ bản không thể bắt chước hoàn toàn -readablevới -perm- xem bình luận trước đây của tôi và xem xét ví dụ sau: echo 'hi' > file; sudo chown nobody:nobody file; sudo chmod o-r file; find file -perm -u=rin file, vì người dùng của nó đọc bit được thiết lập, nhưng nó liên quan đến những nobodyngười sử dụng, chứ không phải dùng hiện hành. Người dùng hiện tại không thể đọc tệp này; thử cat file. Xem thêm: câu trả lời này của tôi.
mkuity0

23

Chuyển hướng lỗi tiêu chuẩn. Ví dụ: nếu bạn đang sử dụng bash trên máy unix, bạn có thể chuyển hướng lỗi tiêu chuẩn sang / dev / null như thế này:

find . 2>/dev/null >files_and_folders

20

Mặc dù các cách tiếp cận ở trên không giải quyết trường hợp cho Mac OS X vì Mac Os X không hỗ trợ -readablechuyển đổi, đây là cách bạn có thể tránh các lỗi 'Quyền bị từ chối' trong đầu ra của mình. Điều này có thể giúp một người nào đó.

find / -type f -name "your_pattern" 2>/dev/null.

Nếu bạn đang sử dụng một số lệnh khác với find, ví dụ, để tìm kích thước của các tệp có mẫu nhất định trong một thư mục 2>/dev/nullvẫn sẽ hoạt động như được hiển thị bên dưới.

find . -type f -name "your_pattern" -exec du -ch {} + 2>/dev/null | grep total$.

Điều này sẽ trả về tổng kích thước của các tệp của một mẫu nhất định. Lưu ý 2>/dev/nullở cuối lệnh find.


Đẹp ràng buộc với OS X! Câu trả lời của Jonathan giải thích phần này 2>/dev/null. Bạn có thể vui lòng giải thích phần -exec du -ch {} + 2>/dev/null | grep total$.
Léo Léopold Hertz 2/2/2016

1
@Masi Bạn có thể sử dụng bất kỳ lệnh nào với -exectùy chọn để thực hiện thêm hành động đối với các tệp hoặc thư mục được tìm thấy bởi findlệnh. du -ch file_patterntính toán kích thước của mỗi tệp khớp file_patternvà dòng cuối cùng của đầu ra đó là tổng cộng của tất cả các tệp khớp với file_pattern. Xem trang người đàn ông cho du. grep totalchỉ lọc các dòng trích xuất tổng số lớn (là dòng cuối cùng).
Bunti

13

Những lỗi này được in ra đầu ra lỗi tiêu chuẩn (fd 2). Để lọc chúng ra, chỉ cần chuyển hướng tất cả các lỗi sang / dev / null:

find . 2>/dev/null > some_file

hoặc đầu tiên tham gia stderr và stdout và sau đó tìm ra các lỗi cụ thể đó:

find . 2>&1 | grep -v 'Permission denied' > some_file

11

Câu trả lời đơn giản:

find . > files_and_folders 2>&-

2>&-đóng ( -) bộ mô tả tệp lỗi tiêu chuẩn ( 2) để tất cả các thông báo lỗi bị tắt tiếng.

  • Mã thoát sẽ vẫn là 1nếu có bất kỳ Permission deniedlỗi '' nào được in

Câu trả lời mạnh mẽ cho GNU find:

find . -type d \! \( -readable -executable \) -prune -print -o -print > files_and_folders

Vượt qua các tùy chọn bổ sung cho findđiều đó -prune(ngăn giảm dần vào) nhưng vẫn -printcó bất kỳ thư mục ( ) nào không ( ) có cả quyền và quyền, hoặc ( ) bất kỳ tệp nào khác.-typed\!-readable-executable-o-print

  • -readable-executablecác tùy chọn là các phần mở rộng GNU, không phải là một phần của tiêu chuẩn POSIX
  • Vẫn có thể trả về ' Permission denied' trên các tệp bất thường / bị hỏng (ví dụ: xem báo cáo lỗi ảnh hưởng đến các hệ thống tệp được gắn trong thùng chứa bằng cách sử dụng lxcfs<v2.0.5)

Câu trả lời mạnh mẽ hoạt động với mọi tương thích POSIX find(GNU, OSX / BSD, v.v.)

{ LC_ALL=C find . 3>&2 2>&1 1>&3 > files_and_folders | grep -v 'Permission denied'; [ $? = 1 ]; } 3>&2 2>&1

Sử dụng một đường ống để truyền luồng lỗi tiêu chuẩn đến grep, loại bỏ tất cả các dòng có chứa 'Permission denied'chuỗi.

LC_ALL=Cbộ các locale POSIX sử dụng một biến môi trường , 3>&2 2>&1 1>&33>&2 2>&1 mô tả trùng lặp tập tin để ống dòng tiêu chuẩn lỗi grep, và [ $? = 1 ]sử dụng []để đảo ngược mã lỗi trả về bởigrep để xấp xỉ hành vi ban đầu của find.

  • Cũng sẽ lọc bất kỳ 'Permission denied'lỗi nào do chuyển hướng đầu ra (ví dụ: nếu files_and_foldersbản thân tệp không thể ghi được)

Bạn nghĩ thế nào về đề xuất câu trả lời của JordiFerran? - - Bạn có thể so sánh câu trả lời của bạn với nó?
Léo Léopold Hertz

2
Tập lệnh shell của câu trả lời đó như đã nêu không phải là mục đích chung (chỉ liệt kê các thư mục khớp với $ {m_find_name}) và chứa một số tùy chọn không liên quan đến câu hỏi (hay, / home *, -maxdepth 5, -follow). Câu trả lời này giải quyết vấn đề cụ thể về 'lọc các thư mục có thể đọc nhưng không thể thực thi' chính xác hơn, trong khi mục đích chung vẫn còn.
wjordan

1
@wjordan: Cảm ơn. Tôi đã xóa nhận xét của mình, nhưng vẫn còn một điểm: -permgiải pháp dựa trên cơ sở không đáng để trình bày, bởi vì về cơ bản hơn trích dẫn cho thấy có gì đó khác với dự định: đó là một thử nghiệm hoàn toàn tập trung vào tệp , liên quan đến chủ sở hữu tệp và nhóm, không ai trong số họ có bất kỳ mối quan hệ được bảo đảm nào với người dùng gọi lệnh (xem câu trả lời này của tôi. Có vẻ như giải pháp GNU đã sửa đổi của bạn hiện không bắt được quyền từ chối các lỗi xuất phát từ các tệp .
mkuity0

Tôi không nhận ra cú pháp bạn đang sử dụng (không phải là GNU cũng như BSD), nhưng hãy để tôi minh họa quan điểm của mình bằng một ví dụ độc lập: echo 'hi' > file; sudo chown nobody:nobody file; sudo chmod o-r file; find file -perm -u=rin file, vì bit đọc của người dùng được đặt, nhưng nó liên quan đến nobodyngười dùng , không phải người dùng hiện tại. Người dùng hiện tại không thể đọc tệp này; thử cat file.
mkuity0

1
@ mkuity0 cảm ơn vì cuộc thảo luận, tôi đã quản lý để tạo ra hành vi mà bạn mô tả trong một thử nghiệm khác (không biết tôi đã làm gì sai lần đầu tiên), có vẻ như điều -permđó không hoạt động để xác định quyền hiện tại của người dùng. Loại bỏ thay thế từ câu trả lời này.
wjordan

4

Để tránh chỉ cho phép cảnh báo bị từ chối, hãy nói tìm để bỏ qua các tệp không thể đọc được bằng cách cắt xén chúng khỏi tìm kiếm. Thêm một biểu thức dưới dạng OR để tìm, chẳng hạn như

find / \! -readable -prune -o -name '*.jbd' -ls

Điều này chủ yếu nói với (khớp một tệp không thể đọc và cắt nó từ danh sách) HOẶC (khớp tên như * .jbd và hiển thị nó [với ls]) . (Hãy nhớ rằng theo mặc định các biểu thức là AND'd trừ khi bạn sử dụng -hoặc.) Bạn cần các -ls trong biểu thức thứ hai hoặc tìm thấy khác có thể thêm một hành động mặc định để hiển thị khớp, nó cũng sẽ hiển thị cho bạn tất cả các tệp không thể đọc được .

Nhưng nếu bạn đang tìm kiếm các tệp thực trên hệ thống của mình, thường không có lý do để tìm trong / dev, trong đó có nhiều tệp, vì vậy bạn nên thêm một biểu thức loại trừ thư mục đó, như:

find / -mount \! -readable -prune  -o  -path /dev -prune  -o  -name '*.jbd' -ls

Vì vậy (khớp tệp không thể đọc và cắt tỉa từ danh sách) HOẶC (khớp đường dẫn / dev và lược từ danh sách) HOẶC (khớp tệp như * .jbd và hiển thị nó) .


4

sử dụng

sudo find / -name file.txt

Thật là ngu ngốc (vì bạn nâng cao tìm kiếm) và không an toàn, nhưng viết ngắn hơn nhiều.


Bạn tìm kiếm ở đây toàn bộ hệ thống tập tin vì vậy bạn có nghĩa là "nâng cao tìm kiếm" này. Tại sao bạn gọi nó là không an toàn? Bởi vì nó đang tìm kiếm toàn bộ hệ thống tập tin?
Léo Léopold Hertz 16/12/14

2
Bởi vì sudo chạy lệnh find với quyền root, về cơ bản là một ý tưởng tồi. Nguyên tắc phân chia và đặc quyền tối thiểu bị vi phạm.
sương mù

3
"Độ cao" ở đây là của các đặc quyền, để root, với sudo. Bạn có nguy cơ khiến toàn bộ hệ thống của mình bị lỗi bởi một lỗi trong findphiên bản độc hại hoặc một lời gọ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.
tripleee 7/12/2015

2

Không có câu trả lời nào ở trên làm việc cho tôi. Bất cứ điều gì tôi tìm thấy trên Internet đều tập trung vào: ẩn lỗi. Không có xử lý đúng quy trình trả về mã / mã thoát. Tôi sử dụng lệnh find trong các tập lệnh bash để xác định vị trí một số thư mục và sau đó kiểm tra nội dung của chúng. Tôi đánh giá lệnh tìm thành công bằng cách sử dụng mã thoát: giá trị 0 hoạt động, nếu không thì thất bại.

Câu trả lời được cung cấp ở trên của Michael Brux đôi khi hoạt động. Nhưng tôi có một kịch bản trong đó nó thất bại! Tôi đã phát hiện ra vấn đề và tự sửa nó. Tôi cần cắt tỉa các tập tin khi:

it is a directory AND has no read access AND/OR has no execute access

Xem vấn đề chính ở đây là: VÀ / HOẶC. Một chuỗi điều kiện được đề xuất tốt mà tôi đọc là:

-type d ! -readable ! -executable -prune

Điều này không hoạt động luôn. Điều này có nghĩa là một prune được kích hoạt khi một trận đấu là:

it is directory AND no read access AND no execute access

Chuỗi biểu thức này không thành công khi quyền truy cập đọc được cấp nhưng không có quyền truy cập thực thi.

Sau một số thử nghiệm, tôi nhận ra điều đó và thay đổi giải pháp shell script của mình thành:

đẹp find / home * / -maxdepth 5 -follow \
    \ (-type d -a \ (-readable -a -executable \)! \) -prune \
    -o \
    \ (-type d -a -a -readable - thực thi -a -name "$ {m_find_name}" \) -print

Chìa khóa ở đây là đặt "không đúng" cho biểu thức kết hợp:

has read access AND has execute access

Nếu không, nó không có quyền truy cập đầy đủ, có nghĩa là: cắt tỉa nó. Điều này đã chứng minh làm việc cho tôi trong một kịch bản mà các giải pháp đề xuất trước đó đã thất bại.

Tôi cung cấp dưới đây chi tiết kỹ thuật cho các câu hỏi trong phần ý kiến. Tôi xin lỗi nếu chi tiết quá mức.

  • Tại sao sử dụng lệnh tốt? Tôi có ý tưởng ở đây . Ban đầu tôi nghĩ sẽ tốt hơn nếu giảm mức độ ưu tiên của quá trình khi tìm kiếm toàn bộ hệ thống tập tin. Tôi nhận ra nó không có ý nghĩa với tôi, vì kịch bản của tôi bị giới hạn trong một vài thư mục. Tôi giảm -maxdepth xuống còn 3.
  • Tại sao tìm kiếm trong / nhà * /? Điều này nó không liên quan đến chủ đề này. Tôi cài đặt tất cả các ứng dụng bằng tay thông qua biên dịch mã nguồn với người dùng không có đặc quyền (không phải root). Chúng được cài đặt trong "/ home". Tôi có thể có nhiều nhị phân và phiên bản sống cùng nhau. Tôi cần xác định vị trí tất cả các thư mục, kiểm tra và sao lưu theo kiểu chủ nô. Tôi có thể có nhiều "/ home" (một số đĩa chạy trong một máy chủ chuyên dụng).
  • Tại sao sử dụng -follow? Người dùng có thể tạo các liên kết tượng trưng đến các thư mục. Nó hữu dụng tùy thuộc, tôi cần ghi lại các đường dẫn tuyệt đối được tìm thấy.

Cảm ơn bạn đã trả lời và quan sát tốt đẹp của bạn! Tôi đã mở một tiền thưởng ở đây để xem trước câu trả lời của bạn tốt hơn. Tôi nghĩ rằng đó là một phát hiện tốt đẹp không ngăn chặn việc đọc và thực hiện truy cập. - - Bạn có thể giải thích lý do tại sao bạn sử dụng nicefind $HOME -maxdepth 5 -follow ...?
Léo Léopold Hertz

2
Các kịch bản shell như đã nêu không phải là mục đích chung (chỉ liệt kê các thư mục phù hợp ${m_find_name}), và chứa một số tùy chọn không liên quan đến câu hỏi ( nice, /home*, -maxdepth 5, -follow). Tôi đã thêm một câu trả lời giải quyết vấn đề cụ thể về 'lọc các thư mục có thể đọc được nhưng không thể thực thi' chính xác hơn, trong khi mục đích chung vẫn còn.
wjordan

2

Bạn có thể sử dụng grep -v invert-match

-v, --invert-match        select non-matching lines

như thế này:

find . > files_and_folders
cat files_and_folders | grep -v "permission denied" > files_and_folders

Nên phép thuật


2

- = Dành cho MacOS = -

Tạo một lệnh mới bằng bí danh: chỉ cần thêm dòng ~ / .bash_profile:

alias search='find / -name $file 2>/dev/null'

và trong cửa sổ Terminal mới, bạn có thể gọi nó:

$ file=<filename or mask>; search

ví dụ:

$ file = vân vân; Tìm kiếm


1

Nếu bạn đang sử dụng CSH hoặc TCSH, đây là một giải pháp:

( find . > files_and_folders ) >& /dev/null

Nếu bạn muốn đầu ra cho thiết bị đầu cuối:

( find . > /dev/tty ) >& /dev/null

Tuy nhiên, như Câu hỏi thường gặp về "csh-whynot" mô tả, bạn không nên sử dụng CSH.


Tôi muốn grep tất cả các tệp txt và loại trừ các tệp / thư mục ẩn, bỏ qua thông báo "Quyền bị từ chối" sẽ được in. Tôi đang sử dụng vỏ csh. Tôi đã sử dụng các lệnh dưới đây và chúng không hoạt động tìm thấy. -type f -iname " .txt" -không -path '* / \. '| egrep -v "Quyền bị từ chối" tìm thấy. -type f -iname " .txt" -không -path '* / \. '2> / dev / null Bắt lỗi bên dưới. find: đường dẫn phải đi trước biểu thức: 2 Cách sử dụng: find [-H] [-L] [-P] [-Olevel] [-D help | cây | search | stat | Rate | opt | exec] [path ...] [biểu hiện]
yadav
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.