it-swarm-vi.com

Làm thế nào để loại bỏ tất cả các thư mục trống trong một cây con?

Làm thế nào tôi có thể loại bỏ tất cả các thư mục trống trong một cây con? Tôi đã sử dụng một cái gì đó như

find . -type d -exec rmdir {} 2>/dev/null \;

nhưng tôi cần được chạy nhiều lần để xóa các thư mục chỉ chứa các thư mục trống. Hơn nữa, nó khá chậm, đặc biệt là dưới cygwin.

159
maaartinus

Kết hợp GNU find tùy chọn và vị từ, lệnh này sẽ thực hiện công việc:

find . -type d -empty -delete
  • -type d giới hạn thư mục
  • -empty hạn chế những cái trống
  • -delete xóa từng thư mục

Cây được đi từ lá mà không cần chỉ định -depth vì nó được ngụ ý bởi -delete.

237

Liệt kê các thư mục lồng nhau sâu trước.

find . -depth -type d -exec rmdir {} \; 2>/dev/null

(Lưu ý rằng chuyển hướng áp dụng cho toàn bộ lệnh find, không chỉ cho rmdir. Chỉ chuyển hướng cho rmdir sẽ gây ra sự chậm lại đáng kể khi bạn cần phải gọi một lớp vỏ trung gian.)

Bạn có thể tránh chạy rmdir trên các thư mục không trống bằng cách chuyển -empty vị ngữ cần tìm. GNU find kiểm tra thư mục khi nó sắp chạy lệnh, vì vậy các thư mục vừa bị xóa sẽ được chọn.

find . -depth -type d -empty -exec rmdir {} \;

Một cách khác để tăng tốc sẽ là nhóm các yêu cầu rmdir. Cả hai đều có khả năng nhanh hơn đáng kể so với bản gốc, đặc biệt là dưới Cygwin. Tôi không mong đợi nhiều sự khác biệt giữa hai điều này.

find . -depth -type d -print0 | xargs -0 rmdir 2>/dev/null
find . -depth -type d -exec rmdir {} + 2>/dev/null

Phương pháp nào nhanh hơn phụ thuộc vào số lượng thư mục không trống của bạn. Bạn không thể kết hợp -empty với các phương thức để nhóm các yêu cầu, bởi vì sau đó các thư mục chỉ chứa các thư mục trống sẽ không trống vào thời điểm find nhìn vào chúng.

Một phương pháp khác là chạy nhiều lượt. Việc này có nhanh hơn hay không phụ thuộc vào rất nhiều thứ, bao gồm cả việc phân cấp toàn bộ thư mục có thể duy trì trong bộ đệm của đĩa giữa find chạy hay không.

while [ -n "$(find . -depth -type d -empty -print -exec rmdir {} +)" ]; do :; done

Ngoài ra, sử dụng zsh. vòng loại toàn cầF khớp với các thư mục không trống, vì vậy /^F khớp với các thư mục trống. Các thư mục chỉ chứa các thư mục trống không thể được so khớp dễ dàng.

while rmdir **/*(/N^F); do :; done

(Điều này chấm dứt khi rmdir nhận được một dòng lệnh trống.)

Nếu bạn chỉ giải quyết -p Trên rmdir, thì nó sẽ hoạt động trong một lần. Nó sẽ không đẹp hoặc tối ưu, nhưng nó sẽ có được mọi thứ. Điều đó nói với rmdir để xóa bất kỳ thư mục cha không trống nào của thư mục bạn đang xóa.

Bạn có thể tiết kiệm một chút bằng cách thêm bài kiểm tra -empty Để tìm, vì vậy nó không bận tâm với các thư mục không trống.

6
mattdm

find . -depth -type d -exec rmdir {} +

là câu trả lời đơn giản và chuẩn nhất cho câu hỏi này.

Thật không may, tất cả các câu trả lời khác được đưa ra ở đây đều phụ thuộc vào các cải tiến cụ thể của nhà cung cấp không tồn tại trên tất cả các hệ thống.

3
schily

Tôi sử dụng các bí danh này cho các lệnh find được sử dụng thường xuyên, đặc biệt là khi tôi dọn sạch không gian đĩa bằng cách sử dụng dupegur, trong đó việc loại bỏ trùng lặp có thể dẫn đến rất nhiều thư mục trống.

Bình luận bên trong .bashrc vì vậy tôi sẽ không quên chúng sau này khi tôi cần Tweak nó.

# find empty directories
alias find-empty='find . -type d -empty'

# fine empty/zero sized files
alias find-zero='find . -type f -empty'

# delete all empty directories!
alias find-empty-delete='find-empty -delete'

# delete empty directories when `-delete` option is not available.
# output null character (instead of newline) as separator. used together
# with `xargs -0`, will handle filenames with spaces and special chars.
alias find-empty-delete2='find-empty -print0 | xargs -0 rmdir -p'

# alternative version using `-exec` with `+`, similar to xargs.
# {}: path of current file
# +: {} is replaced with as many pathnames as possible for each invocation.
alias find-empty-delete3='find-empty -exec rmdir -p {} +'

# for removing zero sized files, we can't de-dupe them automatically
# since they are technically all the same, so they are typically left
# beind. this removes them if needed.
alias  find-zero-delete='find-zero -delete'
alias find-zero-delete2='find-zero -print0 | xargs -0 rm'
alias find-zero-delete3='find-zero -exec rm {} +'
0
raychi

find . -type d -printf "%d %p\n" |\ sort -nr |\ Perl -pe 's/^\d+\s//;' |\ while read dir; do \ (rmdir "$dir" > /dev/null 2>&1); \ done

Đây là cách nó hoạt động:

  1. Danh sách đệ quy tất cả các thư mục cùng với độ sâu của chúng
  2. Sắp xếp theo thứ tự giảm dần độ sâu của chúng
  3. Chỉ lọc các đường dẫn thư mục
  4. Chạy rmdir trên danh sách từng cái một
0
Ashish Ranjan