28

So using the shell, and having a directory:

./parent
./parent/one
./parent/two
./parent/three
./parent/four

i want to do something like rm -rf parent/* in one command, but keeping one directory, for example 'four', so the end result would be

./parent
./parent/four
André Alçada Padez
  • 10,987
  • 24
  • 67
  • 120

4 Answers4

46

With bash you can do this with the extglob option of shopt.

shopt -s extglob
cd parent
rm -rf !(four)

With a posix shell I think you get to use a loop to do this

for dir in ./parent/*; do
    [ "$dir" = "four" ] && continue
    rm -rf "$dir"
done

or use an array to run rm only once (but it requires arrays or using "$@")

arr=()
for dir in ./parent/*; do
    [ "$dir" = "four" ] && continue
    arr+=("$dir")
done
rm -rf "${arr[@]}"

or

for dir in ./parent/*; do
    [ "$dir" = "four" ] && continue
    set -- "$@" "$dir"
done
rm -rf "$@"

or you get to use find

find ./parent -mindepth 1 -name four -prune -o -exec rm -rf {} \;

or (with find that has -exec + to save on some rm executions)

find ./parent -mindepth 1 -name four -prune -o -exec rm -rf {} +

Oh, or assuming the list of directories isn't too large and unwieldy I suppose you could always use

rm -rf parent/*<ctrl-x>*

then delete the parent/four entry from the command line and hit enter where <ctrl-x>* is readline's default binding for glob-expand-word.

Etan Reisner
  • 77,877
  • 8
  • 106
  • 148
19

Easiest and practical way in my opinion is to move the exception to parent folder, delete everthing move it back

mv exceptionFolder ..
rm -rf *
mv ../exceptionFolder .

Edit: If there is no parent directory

mkdir todelete
mv * todelete/
mv todelete/exceptionFolder .
rm -rf todelete
Gediz GÜRSU
  • 555
  • 4
  • 12
8

Another way would be to

rm -r $(ls -A | grep -v important_folder)

ls -A lists all files and folders (other than . and ..).

grep -v expression removes anything matching the grep expression from the list.

Shane Bishop
  • 3,905
  • 4
  • 17
  • 47
Uttarayan
  • 121
  • 3
  • 8
  • 1
    You can also add the `-E` flag to grep to use capture groups and `|` and then you can easily add more folders: `grep -vE "(file1)|(file2)"` finds everything except those two files. – Mitchell Skaggs Dec 30 '21 at 10:49
  • You can also add the `-x` flag to grep to match full lines (in case any other folders include the name of the folder to save) – Mitchell Skaggs Dec 30 '21 at 10:50
3

You can do it with find

 find . -maxdepth 1 ! -name foldder_name -type d -not -path '.' -exec rm -rf {} +

find - Its command search files/directories

-maxdepth 1 - Do not find for foldder_name subcategories

. ! -name foldder_name - It means search in current directory . and do not fide this file with his actual name: ! -name foldder_name

-type d - find only directories

-not -path '.' - do not found hidden folders

-exec rm -rf {} + - remove all found data

Ernestyno
  • 797
  • 1
  • 10
  • 16