Hành vi dự kiến ​​của `find -depth` nếu quyền thực thi bị từ chối cho thư mục con?


7

Tôi muốn biết liệu tôi có thể dựa vào hành vi mà tôi đang thấy khi sử dụng findvới -depthtùy chọn không và người dùng không có quyền thực thi cho thư mục con.

Giả sử cấu trúc thư mục sau:

drwxrwxrwt. 10 root    root     12288 Mar 14 04:31 .
dr-xr-xr-x. 24 root    root      4096 Dec  6 03:33 ..
drwx------   4 root    root      4096 Mar 14 04:03 jen

Chạy lệnh sau với tư cách người dùng không root:

find -type d

Đầu ra là:

.
./jen
find: `./jen': Permission denied

Vì vậy, findtìm thấy thư mục jen và đầu ra đó. Sau đó, nó đã cố gắng hạ xuống thành jen , nhưng không được phép nên nó đã in lỗi. Dòng đầu tiên ở trên được in stdoutvà dòng thứ hai đến stderr.

Bây giờ hãy chạy như sau với tư cách là người dùng không root:

find -depth -type d

Và đầu ra là:

find: `./jen': Permission denied
.

Vì vậy, tên đường dẫn không được xuất ra stdouttrừ khi người dùng có quyền liệt kê nội dung của thư mục.

Đầu ra này là hoàn hảo cho những gì tôi muốn làm. Tuy nhiên, tôi không chắc đây có phải chỉ là sự trùng hợp hay không. Tôi có thể dựa vào hành vi này không?

Tôi đang sử dụng công cụ tìm kiếm GNU 4.4.2. Tôi tự hỏi nếu hành vi này là giống nhau trên tất cả các phiên bản find. Và nếu không, nó ít nhất giống nhau trên tất cả các phiên bản GNU tìm thấy.

Nó không quan trọng với tôi (đối với trường hợp sử dụng này) cho dù jen có được in trong ví dụ đầu tiên hay không . Tôi chỉ tự hỏi nếu tôi có thể phụ thuộc vào nó bị loại trừ khi -depthđược sử dụng. Thông thường, không nên dựa vào hành vi không có giấy tờ. Nhưng, với tôi, tác dụng phụ này có ý nghĩa. Vì vậy, tôi nghĩ rằng đây có thể là hành vi dự định .

Hướng dẫn nói:

- Tùy chọn: -thepth

Xử lý nội dung của mỗi thư mục trước thư mục chính nó.

Đây chính xác là những gì tôi muốn, nhưng không rõ tên đường dẫn của chính thư mục sẽ bị loại khỏi đầu ra nếu nó không đi vào nó.

Nhờ có một gợi ý từ Hauke Laging, tôi phát hiện ra rằng tôi có thể liệt kê chỉ mục và dứt khoát loại trừ thư mục nơi phép liệt kê nội dung của họ bị từ chối:

find -type d \( \( -type d \( \! -executable -or \! -readable \) \) -prune -or -print \)

Điều này cũng có tác dụng ngăn chặn các lỗi "Quyền bị từ chối" vì findkhông bao giờ cố gắng truy cập vào một thư mục nếu nó không có quyền.

Thật không may, có hai lý do tại sao điều này sẽ không hoạt động cho nhu cầu của tôi.

  • Tôi muốn thông báo lỗi
  • Tôi cần -depthtùy chọn

Trích dẫn từ hướng dẫn

Nếu tùy chọn '-depth' có hiệu lực, các thư mục con sẽ được truy cập trong mọi trường hợp. Do đó '-prune' không có hiệu lực trong trường hợp này.

Vì vậy, tôi trở lại nơi tôi bắt đầu.

Vẫn chưa rõ liệu "Xử lý nội dung của từng thư mục trước chính thư mục đó". cũng có nghĩa là "Đừng xử lý thư mục nếu bạn không thể xử lý nội dung của nó".


Những phiên bản findnào bạn muốn xem xét? Trên Solaris 10, find . -type din "."ra thiết bị xuất chuẩn và thiết bị xuất "find: cannot read dir ./jen: Permission denied"chuẩn. find . -depth -type din "find: cannot read dir ./jen: Permission denied"ra stderr và "."stdout. Không in "./jen"ra thiết bị xuất chuẩn.
Đánh dấu Plotnick

@MarkPlotnick Thiếu .là một lỗi sao chép và dán. Tôi đã cập nhật câu hỏi của mình với các chi tiết về các phiên bản và những chi tiết nào tôi hy vọng tôi có thể tin cậy.
toxalot

@MarkPlotnick tôi thấy nó lạ mà Solaris 10 không in ./jencho find . -type d. Nó vẫn là một phần của nội dung .mặc dù findkhông thể đi sâu vào nó. Không gì ./*mẫu glob mở rộng ra trên Solaris 10? Có bao gồm ./jen?
toxalot

Tôi cũng thấy nó bất ngờ, nhưng đó là những gì nó làm. echo ./*đầu ra ./jen. Tôi thiết lập cấu trúc thư mục giống với OP. trusscho thấy rằng findkhông fchdir()đến mở "."fd, sau đó getdents64() = 72, lstat64("jen",...) = 0, openat(..., "jen", ...) => EACCES, sau đó nó sẽ tạo ra các thông báo lỗi, sau đó getdents64() = 0, sau đó dọn dẹp và thoát. Đây là trên bản phân phối Solaris 10 / x86 miễn phí gần đây nhất từ ​​Oracle, Generic_147148-26, trong một phân vùng ufs
Mark Plotnick 17/03/2016

Câu trả lời:


2

Có lẽ cách tiếp cận tốt hơn là xử lý các thư mục đó một cách rõ ràng. Tôi không biết liệu đây có phải là các tính năng tiêu chuẩn hay không nhưng ít nhất với Gnu findthì điều này là có thể:

find . \( -type d \( \! -executable -or \! -readable \) \) -prune -or -type d

Tất nhiên, cũng có thể in một tin nhắn nếu một thư mục bị bỏ qua:

find . \( -type d \( \! -executable -or \! -readable \) \) \
  -printf "Permission denied: %p\n" -prune -or -type d -print

Điều này không cho đầu ra mong muốn. Cấu trúc thư mục trong câu hỏi là một ví dụ. Cấu trúc thực bao gồm các tập tin thông thường. Với -or print, tất cả các loại tập tin được in. Tôi chỉ muốn thư mục.
toxalot

Ngoài nhu cầu loại trừ các tệp thông thường, tôi cũng muốn giữ các thông báo lỗi. Tôi đã cập nhật câu hỏi của mình để phản ánh điều này.
toxalot

@toxalot Tôi đoán rõ ràng rằng -print(tức là phần sau -or) chỉ là một hình nộm cần được thay thế bằng bất cứ thứ gì bạn muốn. Ví dụ, bạn có thể thay đổi điều đó thành -or -type d.
Hauke ​​Laging

Thứ hai chỉ in các thư mục, loại trừ các thư mục nếu không có quyền liệt kê nội dung và in một thông báo lỗi, điều này giúp tôi đi gần hết. Lưu ý rằng -printsau -or -type dlà quan trọng. Bạn không thể chỉ thay thế -or -printvới -or type dnhư đề xuất trong nhận xét. Tuy nhiên, vì -prunekhông có tác dụng khi -depthđược sử dụng, tôi trở lại câu hỏi ban đầu của mình.
độc tố

@toxalot Bạn có thể điều chỉnh -printfphần này theo bất cứ điều gì bạn muốn. Tất nhiên, bạn có thể in một dòng với đường dẫn và dòng khác với thông báo lỗi. -printlà cần thiết sau -orchỉ khi một lệnh in xảy ra trong phần đầu tiên. Bạn không cần -prune(giảm dần vào các thư mục đó là không thể) vì vậy bạn có thể sử dụng depthmà không gặp vấn đề gì.
Hauke ​​Laging
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.