When I use below code in Ubuntu terminal, it works fine:

rm !(*.sh) -rf

But if I place the same line code in a shell script (clean.sh) and run the shell script from terminal, it throws an error:

clean.sh script:

rm !(*.sh) -rf

The error I get:

./clean.sh: line 2: syntax error near unexpected token `('
./clean.sh: line 2: `rm !(*.sh) -rf'

can you help?


rm !(*.sh) is a extglob syntax which means remove all files except the ones that have the .sh extension.

In your interactive bash instance, the shell option extglob is on :

$ shopt extglob 
extglob         on

Now as your script is running in a subshell, you need to enable extglob by adding this at the start of the script :

shopt -s extglob

So your script looks like :

shopt -s extglob
rm -rf -- !(*.sh)


To remove all files except .sh extension ones use GLOBIGNORE (as you don't want to enable extglob) :

rm -rf *

Example :

$ ls -1


$ rm *

$ ls -1
  • can i change my command that do the same without run this? shopt -s extglob? – Tal Aug 4 '15 at 10:50
  • @Tal check my edits.. – heemayl Aug 4 '15 at 10:54
  • 1
    thanks :) (stack overflaw make me write 15 character in comment :( :( :( ) – Tal Aug 4 '15 at 10:57
  • but here there a two good answers! – Tal Aug 4 '15 at 11:36
  • 1
    This should be the accepted answer, since it actually answers the question, while the other one just describes a workaround. – Guntram Blohm Aug 4 '15 at 16:25

Ok, it's a cross-post, but I have to write an answer. ;)

You could use find instead

find . -maxdepth 1 ! -name '*.sh' -exec rm -rf {} \;

You need to turn extglob on:

shopt -s extglob
  • 1
    @Pilot6: See man bash. It enables extended globbing like !(...). – choroba Aug 4 '15 at 10:45
  • can i change my command that do the same without run this? shopt -s extglob – Tal Aug 4 '15 at 10:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.