17

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?

jww
  • 97,681
  • 90
  • 411
  • 885
Bobo
  • 976
  • 2
  • 10
  • 25

3 Answers3

35

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
Community
  • 1
  • 1
Rubens
  • 14,478
  • 11
  • 63
  • 92
  • works like a charm! thanks! (definitely was testing somewhere else, don't wanna break things) – Bobo Jul 30 '13 at 23:49
  • 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. – Rubens Jul 30 '13 at 23:51
  • 1
    for testing use `echo` as in `echo !(mysql|init)` – mnagel Jul 31 '13 at 06:44
  • ok this works in the command line, but not in my script. Syntax error: "(" unexpected – Bobo Jul 31 '13 at 18:34
  • 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 (: – Rubens Jul 31 '13 at 18:41
  • 3
    > 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 http://stackoverflow.com/questions/216995/how-can-i-use-inverse-or-negative-wildcards-when-pattern-matching-in-a-unix-linu – Motin Sep 29 '14 at 14:09
  • 1
    @Motin Duly noted! I've added the information you pointed. Thanks for that! – Rubens Sep 29 '14 at 22:00
  • note: this will not delete hidden directories like `.svn` or `.git` or simliar – staabm Aug 06 '19 at 11:48
6

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.)

chrylis -cautiouslyoptimistic-
  • 75,269
  • 21
  • 115
  • 152
3

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

find . ! -iname mysql ! -iname temp -exec rm -rf {} \;
AlienHoboken
  • 2,750
  • 20
  • 23
  • 5
    this also deletes the files inside the two folders – Bobo Jul 31 '13 at 18:33
  • 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` – mikewaters Mar 25 '17 at 14:16
  • this in turn won't delete anything inside other subdirectories. – kara deniz Jul 22 '19 at 19:40