Ubuntu – Delete all files except specified files/folders using command line

bashcommand line

I have a folder containing a lot of folders and different files with the following structures :

NASA
│
├── a
│   ├── doc1
│   ├── doc2
│   ├── doc3
│   ├── folder1
│   └── folder2
│
├── b
│   ├── doc1
│   ├── doc2
│   ├── doc3
│   ├── folder1
│   └── folder2
│
├── c
│   ├── doc1
│   ├── doc2
│   ├── doc3
│   ├── folder1
│   └── folder2
│
├─ x
├─ y
└─ z     

I want to delete the content of the folder (NASA/) except specified folders and files.

For example I want to keep a folder, b folder and x file.

I tried this solution
:

 rm !(a/) -r NASA/

And (as explained in the answer here):

find NASA/ -type f ! -iname "x" -delete

But this is not very straight forward and I have to use a bash script.

Am I missing a more easy way ? How can I do this in a single command?

Best Answer

You can use GLOBIGNORE to set the names that will be ignored while globbing and then use * to match all other files/directories:

GLOBIGNORE='a:b:x'; rm -r *

Example:

$ tree 
.
├── a
│   ├── 1
│   ├── 2
│   └── 3
├── b
│   ├── 1
│   ├── 2
│   └── 3
├── c
│   ├── 1
│   ├── 2
│   └── 3
├── x
├── y
└── z

/NASA$ GLOBIGNORE='a:b:x'

/NASA$ rm -r *

/NASA$ tree 
.
├── a
│   ├── 1
│   ├── 2
│   └── 3
├── b
│   ├── 1
│   ├── 2
│   └── 3
└── x

Alternately, you can use find, from the NASA directory:

find . -maxdepth 1 ! -name '.' ! -regex '.*/\(a\|b\|x\)$' -exec rm -r {} +

Example:

/NASA$ tree 
.
├── a
│   ├── 1
│   ├── 2
│   └── 3
├── b
│   ├── 1
│   ├── 2
│   └── 3
├── c
│   ├── 1
│   ├── 2
│   └── 3
├── x
├── y
└── z


/NASA$ find . -maxdepth 1 ! -name '.' ! -regex '.*/\(a\|b\|x\)$' -exec rm -r {} +


/NASA$ tree 
.
├── a
│   ├── 1
│   ├── 2
│   └── 3
├── b
│   ├── 1
│   ├── 2
│   └── 3
└── x