Удалить все подкаталоги, кроме одного

10

Предположим, что в текущем каталоге есть несколько подкаталогов, и один из них называется A.

Как удалить все подкаталоги, кроме A с Bash?

Анон
источник

Ответы:

23

Bash расширил сглаживание (сначала проверьте, затем удалите эхо):

shopt -s extglob
echo rm -rf !(A)
TheBonsai
источник
(прежде чем я забуду - вы можете отключить завершение истории стилей CSH, в Bash3 есть ошибка при игнорировании! (. set + H
+1 Баш, если полон сюрпризов! Иногда они такие милые.
Александр Левчук
Вау, очень мило! Работает как положено. С shopt | grep extвы можете увидеть , если плагин включен.
danger89
14
find -maxdepth 1 -type d -not -name A -not -name "." -exec rm -ir {} \;
оборота дотхо
источник
10

Что о:

mv A /tmp/
rm * -rf
mv /tmp/A .

Это позволяет избежать некоторой «шаткости» опечатки в других командах.

казарка
источник
1
+1 за то, что делаешь вменяемое, вместо того чтобы надеяться, что инструменты достаточно умны. Тем не менее, однажды ночью, когда я только изучал Linux, я скопировал ядро ​​в / tmp перед выполнением моей первой перекомпиляции. она не удалась, но стерла старую, поэтому я сказал «нет пота, у меня есть копия», только чтобы обнаружить, что задача cron в полночь стерла его с каждым файлом, который более недели назад находился в / tmp! Я должен был перекомпилировать снова и на этот раз сделать все правильно, или нет перезагрузки для меня!
Хавьер
лучший ответ размещен :)
Уоррен
3

Что-то типа

find . -type d -not -name A -exec rm -ir {} \;

стоит сделать.

редактировать

Это действительно должно быть

find . -type d -maxdepth 1 -not -name A -exec rm -ir {} \;

чтобы предотвратить findповторение ниже A.

оборота агнул
источник
3
Но это также удалит все подкаталоги ниже A, такие как A / foo и A / bar, но сохранит A / A.
TCampbell
Прохладно! Вопросы и ответы переносятся из SO в SF ... но мои правки выше были потеряны ...
agnul
Лучше поменять местами maxdepth и набрать аргументы так: find. -maxdepth 1 -тип d -не -имя A -exec rm -ir {} \;
Spawnrider
1

Я обычно делаю это, работая над командой ls, которая в первую очередь понимает это правильно. я не на Unix-машине, но что-то вроде:

ls -lda "[^ A]"

Как только вы поймете это правильно, направьте его в команду

ls -lda "[^ A]" | xargs rm -rf

Не стесняйтесь редактировать выше, если я неправильно понял свое регулярное выражение ...

Тим Хулихан
источник
Вы не должны анализировать ls: mywiki.wooledge.org/ParsingLs
приостановлено до дальнейшего уведомления.
1

Если вы хотите быть более гибким, но ручным, вы можете сделать:

ls > /tmp/foo
edit /tmp/foo as you like
xargs -a /tmp/foo rm -r

Таким образом, вы можете сделать общий мангинг.

Джо Беда
источник
1

Вот один из способов. Будьте осторожны с такими вещами, хотя, они настолько мощные, что их можно использовать только для добра или зла ...

найти * -типа d | grep -v "^ A" | xargs rm -rf
Дон брэнсон
источник
1

Не используйте find, как некоторые люди показали с -exec и rm, не передавая -print0 для поиска и -0 для xargs. Это будет путать в именах файлов с пробелами или символами новой строки:

$ mkdir 'foo foo'
$ mkdir foo$'\n'foo 
$ find . -type d -exec rm -ir {} \;
rm: cannot remove directory `.'
rm: remove directory `./foo\nfoo'? y
find: `./foo\nfoo': No such file or directory
rm: remove directory `./foo foo'? y
find: `./foo foo': No such file or directory

Вместо этого используйте find -print0 с xargs -0, '-exec command {} +' или -delete, если ваш поиск поддерживает это.

Кайл Брандт
источник
1

В дополнение к более раннему примеру:

find -maxdepth 1 -type d -not -name A -not -name "." -exec rm -ir {} \;

Вы также можете сделать:

find some/subdir -mindepth 1 -maxdepth 1 -type d -not -name A -exec rm -ir {} \;

чтобы избежать необходимости в cd some/subdirпервую очередь.

Lurchman
источник