Назад | Перейти на главную страницу

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

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

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

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

shopt -s extglob
echo rm -rf !(A)
find -maxdepth 1 -type d -not -name A -not -name "." -exec rm -ir {} \;

Что о:

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

Это позволяет избежать некоторых "пугающих" опечаток в других командах.

Что-то вроде

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

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

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

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

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

предотвращать find от рекурсии ниже A.

Обычно я делаю это, создавая команду ls, которая сначала делает все правильно. я не на машине unix, но что-то вроде:

ls -lda "[^ A]"

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

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

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

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

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

Таким образом, вы можете делать общие манипуляции.

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

find * -type d | grep -v "^A" | xargs rm -rf

Не используйте 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, если ваша находка поддерживает это.

В дополнение к предыдущему примеру:

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 первый.