Delete all files and directories but certain ones using Bash

13,250

Solution 1

You may try:

rm -rf !(mysql|init)

Which is POSIX defined:

 Glob patterns can also contain pattern lists. A pattern list is a sequence
of one or more patterns separated by either | or &. ... The following list
describes valid sub-patterns.

...
!(pattern-list):
    Matches any string that does not match the specified pattern-list.
...

Note: Please, take time to test it first! Either create some test folder, or simply echo the parameter substitution, as duly noted by @mnagel:

echo !(mysql|init)

Adding useful information: if the matching is not active, you may to enable/disable it by using:

shopt extglob                   # shows extglob status
shopt -s extglob                # enables extglob
shopt -u extglob                # disables extglob

Solution 2

This is usually a job for find. Try the following command (add -rf if you need a recursive delete):

find . -maxdepth 1 \! \( -name mysql -o -name temp \) -exec rm '{}' \;

(That is, find entries in . but not subdirectories that are not [named mysql or named tmp] and call rm on them.)

Solution 3

You can use find, ignore mysql and temp, and then rm -rf them.

find . ! -iname mysql ! -iname temp -exec rm -rf {} \;
Share:
13,250
Bobo
Author by

Bobo

Recent graduate with a double major in Computer Science and Mathematics. Currently working as a Software Developer I in a financial institution.

Updated on June 03, 2022

Comments

  • Bobo
    Bobo almost 2 years

    I'm writing a script that needs to erase everything from a directory except two directories, mysql and temp.

    I've tried this:

    ls * | grep -v mysql | grep -v temp | xargs rm -rf
    

    but this also keeps all the files that have mysql in their name, that i don't need. it also doesn't delete any other directories.

    any ideas?

  • Bobo
    Bobo almost 11 years
    works like a charm! thanks! (definitely was testing somewhere else, don't wanna break things)
  • Rubens
    Rubens almost 11 years
    If this answers your question, mark the answer as accepted. It both allows others to know the question has been answered, as it means you acknowledge others effort to help you. To accept an answer, click on the tick mark, below the voting arrows.
  • mnagel
    mnagel almost 11 years
    for testing use echo as in echo !(mysql|init)
  • Bobo
    Bobo almost 11 years
    this also deletes the files inside the two folders
  • Bobo
    Bobo almost 11 years
    this also deletes the files inside the two folders
  • Bobo
    Bobo almost 11 years
    ok this works in the command line, but not in my script. Syntax error: "(" unexpected
  • Rubens
    Rubens almost 11 years
    I'm sure this is worth another question! Would you mind to post it? -- I sincerely do not know a solution, but I'm still searching (:
  • chrylis -cautiouslyoptimistic-
    chrylis -cautiouslyoptimistic- almost 11 years
    Not with the maxdepth option. Remove the -exec rm '{}' \; to get a list of the matching files, which won't include anything below ./.
  • Motin
    Motin over 9 years
    > ok this works in the command line, but not in my script. Syntax error: "(" unexpected In a script, you need to explicitly enable extended globbing. Put this anywhere above the line: shopt -s extglob See stackoverflow.com/questions/216995/…
  • Rubens
    Rubens over 9 years
    @Motin Duly noted! I've added the information you pointed. Thanks for that!
  • Jon L.
    Jon L. over 9 years
    This returns back . as well, so if you're executing rm -Rf, could potentially delete more than you intend...
  • ishmael
    ishmael about 7 years
    Add -mindepth 1 to avoid deleting the current directory.
  • mikewaters
    mikewaters about 7 years
    To not delete everything inside these folders, use find . -maxdepth 1 ! -iname mysql ! -iname temp -exec rm -rf {} \;, or even better find . -maxdepth 1 ! -iname mysql ! -iname temp -delete
  • kara deniz
    kara deniz almost 5 years
    this in turn won't delete anything inside other subdirectories.
  • staabm
    staabm almost 5 years
    note: this will not delete hidden directories like .svn or .git or simliar