Xóa các thư mục con trống, giữ thư mục cha


15

Khi tôi sử dụng

find /home/user/parentdir -type d -empty -delete

nó trông đệ quy cho các thư mục con trống bên trong /home/user/parentdirvà xóa chúng. Nhưng nếu /home/user/parentdircũng trống, nó cũng xóa parentdirthư mục, đó là điều không mong muốn đối với tôi.

Tôi muốn giữ điều này parentdircho rsyncmột số tệp để sao lưu hoặc đám mây. Sau khi xử lý, tôi cần xóa các thư mục trống, nhưng dường như không hiệu quả để tạo lại parentdirmỗi lần.

Bất cứ đề nghị để giữ parentdir? Tôi nghĩ về việc tạo một .nocopytập tin bên trong nó và loại trừ nó khỏi rsync, nhưng có vẻ như quá mức cần thiết. Có cách nào thanh lịch hơn?


nếu bạn thêm một dấu gạch chéo về phía trước / vào cuối của / Parentdir (tức là / Parentdir /) thì điều đó có tạo ra sự khác biệt không?
Graham

6
-mindepth 1?
Steeldo

@Graham / Parentdir / cũng xóa Parentdir, do đó không có sự khác biệt.
TNT

ah, tôi thấy tôi đã bỏ lỡ * ở cuối mà @Amourk đề cập đến trong câu trả lời của anh ấy.
Graham

Câu trả lời:


25

Đơn giản chỉ cần làm find /home/user/parentdir -mindepth 1 -type d -empty -delete.

Nhìn:

$ mkdir -p test1/test2
$ find test1 -type d
test1
test1/test2
$ find test1 -mindepth 1  -type d
test1/test2

Các find /home/user/parentdir/* trong câu trả lời của AmourK là không mong muốn khi có rất nhiều các tập tin và nó được overcomplicated.


15

Bằng cách thêm /*vào cuối parentdir, bạn đang thực hiện hành động trên tất cả các thư mục con của cha mẹ chứ không phải trên parentdirchính nó. Và theo cách tương tự /home/user/không bị xóa trong lệnh cũ, parentdirsẽ không bị xóa trong lệnh bên dưới. *được gọi là toán tử toàn cục và nó khớp với bất kỳ chuỗi ký tự nào.

find /home/user/parentdir/* -type d -empty -delete


7
Một điều cần lưu ý với phương pháp này là nếu có một số lượng lớn tệp /home/user/parentdir/, toàn cầu mở rộng có thể vượt quá ARG_MAX, dẫn đến một danh sách đối số lỗi quá dài . Bạn có thể giảm khả năng điều đó xảy ra bằng cách thay đổi toàn cầu để */nó chỉ khớp với các thư mục.
Steeldo

12
Cũng cần lưu ý rằng điều này sẽ không tìm thấy bất kỳ đứa trẻ nào bắt đầu bằng một dấu chấm. Và một ngày nào đó bạn sẽ nhận ra điều này, và nếu bạn cũng tìm thấy ". *", Bạn sẽ ở trong một thế giới bị tổn thương lớn (vì ". *" Khớp ".."). Hỏi tôi làm sao tôi biết.
Glenn Willen

1
@GlennWillen tại sao tôi nghĩ rằng chúng ta nên ngồi ở một quán bar với đồ uống trước mặt chúng tôi trước khi tôi yêu cầu bạn kể câu chuyện này?
Monty Harder

@MontyHarder Thật may là nó không tệ như nó có thể xảy ra. Đó là trên hệ thống Unix đầu tiên của tôi, đó là một máy Solaris thuộc sở hữu của trường trung học của tôi. Cảm ơn chúa tôi đã không chạy 'rm', mà là 'chown'. Tôi đã sử dụng root để cố gắng sửa quyền sở hữu mọi thứ trong thư mục nhà của tôi. Thay vào đó, tôi tự cho mình quyền sở hữu MỌI thư mục nhà (và tất cả nội dung của chúng) và sau đó phải đặt lại tất cả.
Glenn Willen

Tôi đã có một đồng nghiệp đào tạo một nhân viên mới về cách cài đặt một phần mềm. Nó liên quan đến việc đi đến /tmp, tạo một thư mục con, giải nén một tarball được nén ở đó, chạy trình cài đặt và dọn dẹp. Người mới nghĩ rm -rf /tmp/foo-installlà cách đúng đắn để làm điều đó, và khi bàn tay có kinh nghiệm nói "Noooooo" trong ấn tượng Darth-Vader-at-the-the-end-of-Episode-III tốt nhất của anh ấy, người mới phát hiện ra cách khó khăn / và phím Enter là của nhau. Chúng tôi phải khởi động từ đĩa khôi phục của phần mềm sao lưu và tải lại toàn bộ máy chủ từ băng.
Monty Harder

0

nếu bạn đã cài đặt php-cli,

printf %s $(pwd) | php -r 'function f(string $dir){var_dump($dir);$dir.=DIRECTORY_SEPARATOR;foreach(glob("$dir*",GLOB_ONLYDIR) as $d){f($d);}global $original;if(substr($dir,0,-strlen(DIRECTORY_SEPARATOR))!==$original && empty(glob("$dir*"))){rmdir($dir);}}f(($original=stream_get_contents(STDIN)));'

bạn muốn foreach (RecursiveIteratorIterator(RecursiveDirectoryIterator($dir)) as $p) if (empty($skipped)) $skipped = TRUE; elseif ($p->isDir()) @rmdir($p->getPathname());hoặc một cái gì đó gần với điều đó. $skippedchăm sóc bỏ qua cái đầu tiên, @rmdircố gắng xóa một thư mục và âm thầm (đó là @) không thành công nếu không trống.
chx

0

Khi bạn chỉ cần một cấp độ (để lại một thư mục mẹ, nhưng xóa các thư mục con trống), một mẹo đơn giản là sử dụng rmdir.

rmdir parent/*

Xóa tất cả các thư mục con trống, nhưng chỉ in một lỗi cho các tệp và thư mục không trống.

Điều này không hoạt động đệ quy, nhưng khi biết cấu trúc thư mục của bạn, nó có thể là cách nhanh nhất để làm một cái gì đó như

rmdir parent/*/*/* # deletes parent/a/b/c when empty
rmdir parent/*/* # deletes parent/a/b when it is now empty
rmdir parent/* # deletes parent/a when it is now empty

Ưu điểm: Dễ nhớ, gõ nhanh, ít tiềm năng chọn sai tham số.
Nhược điểm: Ít linh hoạt, có thể rất nhiều thông báo lỗi trong thiết bị đầu cuối của bạn.

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.