Как удалить все файлы/папки из папки, кроме нескольких папок?

Я пытаюсь написать сценарии поддержки для пакета debian. Предположим, что у меня есть следующая структура каталогов:

application/
----application/file1.txt
----application/file2.txt
----application/config
--------application/config/c1.conf
--------application/config/c2.conf
----application/logs
--------application/logs/l1.txt
--------application/logs/l2.txt
----application/src
--------application/src/static/
------------application/src/static/js
------------application/src/static/css
--------application/src/s1.py
--------application/src/s2.py
----application/lib
--------application/src/js/
--------application/src/css/

Теперь я хочу удалить все файлы/папки, кроме config и logs (в данном случае папки src и lib, а также файлы file1.txt и file2.txt). Мой PWD в настоящее время является родителем каталога appliaction/ (т. е. я вижу application в своем PWD).

Какую команду мне следует использовать (небольшой bash script было бы здорово)? (Я пытался использовать rm -rf с некоторыми параметрами, но по ошибке удалил другие файлы, поэтому я хотел бы знать правильный ответ, прежде чем пытаться что-либо еще!)


person exAres    schedule 08.08.2014    source источник
comment
Какие варианты вы пробовали? Потому что вы можете сделать это с помощью простого rm (см. мой ответ).   -  person Bernhard    schedule 14.08.2014


Ответы (6)


Из того, что я понял, есть куча других папок, кроме src, потому что иначе вы бы просто использовали rm -rf src.

Если ваш PWD равен application, то есть вы находитесь в родительском каталоге config logs и src, вам просто нужен способ использовать rm -rf для всех файлов/папок, кроме config и log, так почему бы не сделать цикл for?

    #!/bin/bash

    cd "/path/to/application"

    for file in * ; do
            case "$file" in
                    config )
                            echo "file is $file: doing nothing"
                    ;;
                    logs )
                            echo "file is $file: doing nothing"
                    ;;
                    * )
                            echo "file is $file: removing"
                            rm -rf "$file"
                    ;;
                    esac
            done
    exit 0
person Brian Albert Monroe    schedule 08.08.2014
comment
Это не удаляет файлы. - person Bernhard; 14.08.2014
comment
Пожалуйста, проверьте исходный пост под правками. В частности, это были папки. файлы/папки были добавлены в вопрос после того, как я предоставил свой ответ. В любом случае, чтобы удалить файлы, просто удалите оператор if из приведенного выше, и при условии, что нет файлов с именем config или журналов без каких-либо расширений, этот скрипт будет работать так, как предполагалось. - person Brian Albert Monroe; 14.08.2014
comment
Ах, я ненавижу, когда люди так сильно меняют свой вопрос. Но, может быть, тогда лучше удалить оператор if, чтобы сохранить его согласованность? - person Bernhard; 14.08.2014
comment
Конечно, изменения внесены. Я новичок на этих форумах и не совсем уверен, что такое этикет, когда исходное сообщение изменяется после того, как был предоставлен правильный ответ. Если бы вы не указали обновленный вопрос, я бы, вероятно, никогда не проверил это. - person Brian Albert Monroe; 14.08.2014
comment
Ну, обычно это не очень ценится, но в данном случае это не сильно повредит. Я проголосовал, потому что это решение должно работать, хотя я думаю, что мое лучше;) - person Bernhard; 14.08.2014

Это должно работать:

find ./application -depth -mindepth 1 -type d \
  -regextype posix-extended ! -regex ".*\/(config|logs).*" | \
  -exec rm -fr {}  \;

Или с помощью xargs, если у вас нет имен папок с символами новой строки, вы можете написать:

find ./application -depth -mindepth 1 -type d \
  -regextype posix-extended ! -regex ".*\/(config|logs).*" | \
  xargs -t -I {} rm -fr {}

Или с xargs, если у вас есть имена папок с символами новой строки, которые вы можете использовать:

find ./application -depth -mindepth 1 -type d \
  -regextype posix-extended ! -regex ".*\/(config|logs).*" -print0 | \
  xargs -0 -t -I {} rm -fr {}
  • find находит все каталоги ниже ./application, за исключением тех, у которых есть /config и /logs, и печатает их, начиная с самого нижнего
  • xargs запускает удаление каталога
person Community    schedule 08.08.2014

Поскольку вы просто удаляете каталог application/application/src, нет причин использовать find и т. д. Все, что вам нужно сделать, это:

rm -rf application/application/src

осталось:

application/application/logs/l2.txt
application/application/logs/l1.txt
application/application/config/c1.conf
application/application/config/c2.conf
person David C. Rankin    schedule 08.08.2014

cd application
find . -type d | egrep -v '(^\./$|^\./log|^\./config)' | while read DIR
do
   echo rm -rf $DIR
done

Это использует find для перечисления всех каталогов, передает через grep, чтобы исключить те, которые мы хотим сохранить (также для исключения «./», что будет PWD), и передает этот отфильтрованный список в цикл while, который выполняет удаление. Я поместил туда «эхо», чтобы вы могли проверить, делает ли это то, что вы действительно хотите. Если вы счастливы, удалите эхо. Поскольку возвращаемый список (DIR) будет в порядке дерева, например. d1, d1/d1a, d1/d1b и rm -rf d1 удалит нижние папки, вы можете добавить «if [ -d $DIR]» вокруг rm -rf.

person TenG    schedule 08.08.2014
comment
К сожалению, слишком поздно, мой ответ совпадает с ответом skwilsp. Он зашел, пока я писал свой. Я думаю, что он более краток, хотя. - person TenG; 08.08.2014
comment
Никогда не используйте переменные с заглавной буквы в bash, оставьте их обратными для системных переменных. - person Bernhard; 14.08.2014

Использование Баша:

for file in applications/*; do
    target="${file#*/}"
    if [[ $target != config && $target != logs ]]; then
        rm -rf "$file"
    fi
done
person John B    schedule 08.08.2014

Нет необходимости в сложных find командах, просто используйте оболочку (при условии, что вы находитесь в папке приложения):

rm -r !(logs|config)

Это называется «Расширение имени пути» от man bash

         !(pattern-list)
                Matches anything except one of the given patterns
person Bernhard    schedule 14.08.2014