tìm tất cả các thư mục con cuối cùng trong một cái cây


11

đưa ra cấu trúc sau:

oz123@debian:~/ $ tree .
.
├── a
│   ├── a1
│   ├── a2
│   └── a3
├── a1
│   ├── a11
│   ├── a12
│   └── a31
├── b
│   └── b1
│       ├── b11
│       │   └── b21
│       │       └── b31
│       ├── b12
│       └── b3
└── c

16 directories, 0 files

Làm thế nào để tôi tìm thấy tất cả các nút cuối?

Tôi tìm thấy các giải pháp sau đây có vẻ là tốt, nhưng tôi phải chứng minh rằng không có trường hợp thử nghiệm nào sẽ thất bại.

Trang trợ giúp của các -linkstiểu bang:

Bạn cũng có thể tìm kiếm các tệp có số lượng liên kết nhất định, với '-links'. Thư mục thường có ít nhất hai liên kết cứng; của chúng . mục nhập là cái thứ hai. Nếu chúng có các thư mục con, thì mỗi thư mục đó cũng có một liên kết cứng được gọi là .. đến thư mục mẹ của nó. Các . và .. các mục thư mục thường không được tìm kiếm trừ khi chúng được đề cập trên dòng lệnh find.

giải pháp có thể:

oz123@debian:~/ $ find .  -type d  -links 2
./a/a2
./a/a3
./a/a1
./c
./a1/a31
./a1/a11
./a1/a12
./b/b1/b12
./b/b1/b3
./b/b1/b11/b21/b31
  • Bất cứ ai cũng có thể cung cấp một giải pháp tốt hơn (không cần sử dụng ống và sed, đây có thể là hiệu suất ...)
  • Nó sẽ làm việc trên bất kỳ hệ thống tập tin?

3
Bạn sẽ không tìm thấy nhiều hiệu suất hơn -links 2lừa. Nó sẽ không hoạt động btrfs.
Stéphane Chazelas

Câu trả lời:


3

Là một bổ sung cho giải pháp của riêng bạn -links, tôi muốn thêm rằng nó sẽ không hoạt động trên các hệ thống tập tin không tuân theo quy ước liên kết thư mục Unix. Từ man findtùy chọn -noleafnày, ít nhất là các hệ thống tập tin CD-ROM, MS-DOS và các điểm gắn kết âm lượng AFS.

Để tham khảo, câu hỏi này đã được thảo luận với các giải pháp khác nhau thực sự chậm hơn và thường sử dụng đường ống để sed / awk và tương tự.


3

Có một tùy chọn rõ ràng hơn một chút -empty:

find . -type d -empty

cập nhật. Ok, bạn đúng cách này sẽ không hoạt động với các tệp trong thư mục.

Vì vậy, đây là một hệ thống tập tin cố định phiên bản không thể bỏ qua:

find dtest/ -type d -exec sh -c "if [ \$(find {} -maxdepth 1 -type d | wc -l) -eq 1 ]; then echo {} ; fi" \;

2
Nếu tôi hiểu câu hỏi, thư mục cuối có thể chứa các tệp. Điều này sẽ không in các thư mục đó vì chúng sẽ không "trống" ...
Stefan

@rush, các thư mục con có thể trống hoặc không
Oz123

@ Oz123 vui lòng kiểm tra cập nhật của tôi, nó sẽ đủ nhanh, nhưng chậm hơn một chút so với cách của bạn.
vội vàng

@rush, cảm ơn, nhưng tôi thực sự cần tránh các đường ống, chúng có thể làm mọi thứ chậm hơn.
Oz123

1

find . -type d -links 2hoạt động trên hầu hết các hệ thống tập tin, nhưng không phải tất cả. Tôi không nghĩ có cách nào khác ngoài việc biết loại hệ thống tập tin nào có thuộc tính mà thư mục chứa liên kết đến chính chúng. GNU find phát hiện điều này một cách linh hoạt (nếu nó in ra một cái gì đó về về Tự động bật tùy chọn -noleaf của find, bạn biết hệ thống tập tin của bạn không có thuộc tính này). Hầu hết các loại hệ thống tập tin phổ biến là ok, nhưng không phải là FAT hoặc btrfs.

Nếu bạn muốn chắc chắn, bạn sẽ phải kiểm tra từng thư mục. Một cách để làm điều này là gọi findlại cho mỗi thư mục con.

find . -type d ! -exec sh -c '
   find "$1/." ! -name . -type d -prune | grep -q "^"' sh {} \; -print

(với GNU find, bạn có thể thay thế -prunebằng -print -quitđể làm cho nó hiệu quả hơn một chút).

Một cách khác là xử lý hậu kỳ của đầu ra find. Với find -depth, một thư mục lá là một thư mục không theo thư mục con của chính nó.

find . -depth -type d -print0 |
awk -v RS='\0' '
    substr(previous, 1, length($0) + 1) != $0 "/"
    { previous = $0 }
'

0

Hãy thử giải pháp sau (nên tương thích với Linux, Unix và OS X):

find . -type d -execdir sh -c 'test -z "$(find "{}" -mindepth 1 -type d)" && echo $PWD/{}' ';'

Đó là cách tiếp cận tương tự với giải pháp vội vàng , nhưng không có bất kỳ đường ống.

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.