Xóa cây thư mục trống (loại bỏ càng nhiều thư mục càng tốt nhưng không có tệp)


12

Giả sử tôi có một cây dir như thế này:

ROOTDIR
    └--SUBDIR1
        └----SUBDIR2
            └----SUBDIR3

Tôi đang tìm kiếm một lệnh sao cho khi tôi nhập:

$ [unknown command] ROOTDIR

Toàn bộ cây dir có thể bị xóa nếu không có tệp mà chỉ có các dir bên trong toàn bộ cây . Tuy nhiên, giả sử nếu có một tệp có tên hello.pdf trong SUBDIR1:

ROOTDIR
    └--SUBDIR1
        └--hello.pdf
        └----SUBDIR2
            └----SUBDIR3

Sau đó, lệnh chỉ phải xóa SUBDIR2 trở xuống.


Câu trả lời:


11

Alexis gần gũi. Những gì bạn cần làm là đây:

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

Điều đó trước tiên sẽ đi sâu vào cây thư mục cho đến khi nó tìm thấy thư mục trống đầu tiên, sau đó xóa nó. Do đó, làm cho thư mục mẹ trống sau đó sẽ bị xóa, v.v ... Điều này sẽ tạo ra hiệu ứng mong muốn (tôi làm điều này có thể 10 lần một tuần, vì vậy tôi khá chắc chắn rằng nó đúng). :-)


Tại sao -depthtùy chọn cần thiết? find . -type d -empty -exec rmdir "{}" \;cũng nên làm việc .... đúng không?
Abhishek A

4
Xem xét nếu bạn có một cây (chỉ thư mục) foo/bar/baz. Trừ khi bạn sử dụng -depth, nó sẽ cố xóa footrước, thất bại và bạn sẽ kết thúc foo/barsau khi chạy.
l0b0

1
Có thể thay thế là sử dụng +thay vì ;vậy bạn loại bỏ các thư mục. Vì bạn đang làm điều đó trước tiên, trẻ em vẫn sẽ bị xóa trước cha mẹ (có thể phụ thuộc vào phiên bản rmdir / bash của bạn và phụ thuộc vào rmdir không xóa các thư mục không trống). Điều này làm việc cho tôi trong bash trên cygwin:mkdir -p a/b/c/d ; find a -depth -type d -exec rmdir {} +
idbrii

3
Mọi người, hãy tìm câu trả lời ngắn gọn hơn nhiều của go2null dưới đây! Không thể hiểu tại sao SE ưu tiên cho các câu trả lời được chấp nhận hơn là các câu trả lời với hầu hết các câu trả lời trong việc hiển thị các câu trả lời bên dưới câu hỏi. OP chấp nhận câu trả lời tốt nhất có sẵn tại thời điểm anh ta chọn, nhưng sau đó, câu trả lời tốt hơn nhiều có thể đến mà cộng đồng ủng hộ, không? (Tất nhiên, đây là thứ dành cho meta ...)
jamadagni

Điều này không làm việc cho tôi. nó chỉ xóa lá sâu nhất (SUBDIR3 trong trường hợp này)
joey baruch

23
find ROOTDIR -type d -empty -delete

giống như

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

nhưng sử dụng hành động "-delete" tích hợp.

Lưu ý rằng "-delete" ngụ ý "-depth".


Kudos cho câu trả lời ngắn gọn nhất bằng cách sử dụng xóa tích hợp của find find! Tôi đang thêm điều này vào các bản tin địa phương của tôi!
jamadagni

3

Tôi sẽ thử điều này:

find ROOTDIR -type d -depth -exec rmdir {} \;

1

Dưới đây là một số yêu cầu trước khi chúng tôi có thể làm điều đó một cách an toàn:

  1. xóa thư mục con trước rồi đến thư mục cấp trên, tức là chúng ta cần sắp xếp danh sách thư mục hoặc sử dụng cờ rmdir --parents
  2. bắt đầu ROOTDIR luôn bằng / hoặc ./ để tránh những bất ngờ với các tệp bắt đầu bằng -
  3. sử dụng danh sách các thư mục kết thúc NUL để làm việc với các tên thư mục có khoảng trắng

Đây là cách tôi làm điều đó trong shell:

find ./ROOTDIR -type d | sort -r | tr '\n' '\000' | xargs -0 rmdir --ignore-fail-on-non-empty

Nếu bạn không bận tâm đến một số lỗi dư thừa thì bạn chỉ có thể buộc xóa tất cả các thư mục với cha mẹ và bạn không cần thực hiện bất kỳ sắp xếp nào (bạn không thể sắp xếp các chuỗi kết thúc NUL cần thêm tr)

find ./ROOTDIR -type d -print0 | xargs -0 rmdir --ignore-fail-on-non-empty --parents

Kudos cho lời giải thích chi tiết câu trả lời của bạn. Có lẽ tôi đã sử dụng cách tiếp cận tương tự, cho đến khi tôi biết về -empty -deletecác tùy chọn findtrong câu trả lời của @ go2null.
Davor Cubranic

0
rmdir $(find ROOTDIR -type d | sort -r)

5
Điều này sẽ không hoạt động nếu bất kỳ tên thư mục nào chứa các ký tự khoảng trắng hoặc toàn cầu. Nói chung, đó là một ý tưởng tồi để sử dụng thay thế lệnh trong danh sách tên tệp. Đó đặc biệt là một ý tưởng tồi với findfindcó cách xử lý sạch sẽ : find … -exec.
Gilles 'SO- ngừng trở nên xấu xa'

Cảm ơn Gilles đã chỉ ra điều đó. @lanzz, thường chỉ đăng một lệnh mà không giải thích nó làm gì (và trong trường hợp này, những cạm bẫy) là không đủ. Vui lòng thêm vào câu trả lời của bạn.
n0pe

0

Tôi sẽ làm điều này:

find ROOTDIR -type d | xargs -0 -I {} rmdir {}
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.