Видаліть порожні підпапки, збережіть батьківську папку


15

Коли я використовую

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

він рекурсивно шукає порожні підпапки всередині /home/user/parentdirта видаляє їх. Але якщо /home/user/parentdirвін також порожній, він також видаляє parentdirпапку, що для мене небажано.

Я хочу зберегти це parentdirв rsyncдеяких файлах для резервного копіювання або хмари. Після обробки мені потрібно видалити порожні папки, але це видається непродуктивним для parentdirкожного відтворення .

Будь-які пропозиції зберегти parentdir? Я думав створити .nocopyфайл всередині нього і виключити його з rsync, але виглядає як надмірність. Чи є більш елегантний спосіб?


якщо ви додаєте косу рису вперед / до кінця / parentdir (тобто / parentdir /), це має значення?
Грем

6
-mindepth 1?
steeldriver

@Graham / parentdir / також видаляє parentdir, тому немає ніякого значення.
ТНТ

ах, я бачу, що я пропустив * в кінці, який @Amourk згадує у своїй відповіді.
Грем

Відповіді:


25

Просто робіть find /home/user/parentdir -mindepth 1 -type d -empty -delete.

Подивіться:

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

Відповідь find /home/user/parentdir/* AmourK небажана, коли файлів багато, і вона є складною.


15

Додавши /*в кінці parentdir, ви виконуєте дію над усіма підкаталогами parentdir, а не над parentdirсобою. І тому таким же чином /home/user/не видаляється в старій команді, parentdirне буде видалено в команді нижче. *називається глобальним оператором і відповідає будь-якому рядку символів.

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


7
Одне, що слід пам’ятати при такому підході, - якщо є велика кількість файлів /home/user/parentdir/, розширений глобус може перевищувати ARG_MAX, що призводить до занадто довгої помилки у списку аргументів . Ви можете зменшити ймовірність того, що це станеться, змінивши глобус */так, щоб він відповідав лише каталогам.
steeldriver

12
Також майте на увазі, що це не знайде дітей, починаючи з крапки. І колись ти це зрозумієш, і якщо ти теж знайдеш для ". Запитайте мене, як я знаю.
Глен Віллен

1
@GlennWillen чому я думаю, що ми повинні сидіти в барі з напоями перед нами, перш ніж попросити вас розповісти цю історію?
Monty Harder

@MontyHarder На щастя це було не так погано, як могло бути. Це було за моєю першою системою Unix, яка була машиною Solaris, що належить моїй середній школі. Слава богу, що я не працював на "rm", а швидше на "chown". Я використовував root, щоб спробувати виправити право власності на все в домашньому каталозі. Натомість я дав собі право на ВСІ домашні довідники (і весь їхній вміст), а потім повинен був повернути їх назад.
Гленн Віллен

У мене був колега, який навчав нового працівника щодо встановлення програмного забезпечення. Це стосувалося переходу /tmp, створення підкаталогу, розпакування gzipped тарболу там, запуск інсталятора та прибирання. Новачок подумав, що rm -rf /tmp/foo-installце правильний спосіб зробити це, і, як досвідчена рука сказала "Noooooo" у своєму кращому враженні Дарта-Вейдера-наприкінці епізоду-III, новачок з'ясував важкий шлях, наскільки близько / і клавіші Enter були один для одного. Нам довелося завантажитися з диска відновлення програмного забезпечення для резервного копіювання та перезавантажити весь сервер зі стрічки.
Monty Harder

0

якщо у вас встановлений 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)));'

ти хотів foreach (RecursiveIteratorIterator(RecursiveDirectoryIterator($dir)) as $p) if (empty($skipped)) $skipped = TRUE; elseif ($p->isDir()) @rmdir($p->getPathname());або щось близьке до цього. $skippedпіклується про пропуск першого, @rmdirнамагається вийняти dir і мовчки (це @) не вдається, якщо не порожній.
chx

0

Коли вам потрібен лише один рівень (залишити батьківську папку, але видалити порожні дочірні папки), використовувати простий трюк rmdir.

rmdir parent/*

Видаляє всі порожні папки, але друкує помилку лише для файлів та непустих папок.

Це не працює рекурсивно, але, знаючи структуру вашої папки, це може бути найшвидший спосіб зробити щось подібне

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

Перевага: легко запам'ятовується, швидко набирається, мало потенціалу для вибору неправильного параметра.
Недолік: Менш гнучка, можливо, багато повідомлень про помилки у вашому терміналі.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.