Syntax error near unexpected token `('

Solution 1:

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 :

#!/bin/bash
shopt -s extglob
rm -rf -- !(*.sh)

EDIT :

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

#!/bin/bash
GLOBIGNORE='*.sh'
rm -rf *

Example :

$ ls -1
barbar
bar.sh
egg
foo.sh
spam

$ GLOBIGNORE='*.sh'

$ rm *

$ ls -1
bar.sh
foo.sh

Solution 2:

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 {} \;