1

I'm trying to delete some files and folders from a directory. The command (from here):

rm -rf !(file_i_don't_want_to_remove|other|other_one)

Runs fine in terminal, but if I try to use it inside a script (created using vim, 2 lines):

#!/bin/bash
rm -rf !(one|two)

./file.sh: línea 2: error sintáctico cerca del elemento inesperado `('

Translated:

./file.sh: line 2: syntax error near of unexpected element `('

Why?

PS. I've looked for other questions with the same name but they're all too specific for each script and seem not to be the same problem than mine.

Btc Sources
  • 1,912
  • 2
  • 30
  • 58
  • Just a suggestion why don't you loop through all the files which you want to delete eg--> `.txt` or `.jpg` etc and delete them, just a suggestion. – RavinderSingh13 Dec 03 '18 at 13:24
  • 1
    Is the `bash` in your script as new as the one in your Terminal? You need to also set `shopt -s extglob` for that I think. – Mark Setchell Dec 03 '18 at 13:24
  • @RavinderSingh13 may be recursive, more lines for no advantage IMHO. – Btc Sources Dec 03 '18 at 13:29
  • @MarkSetchell I've no idea at all. I've just found the command, tried it in my terminal and it worked, and then tried to use it in a script. I've never used `shopt` command nor know what does it do. Going to research a bit. Thanks for the clue. – Btc Sources Dec 03 '18 at 13:31

1 Answers1

4

You need the extglob extension enabled for this syntax to work:

#!/bin/bash
shopt -s extglob
cd /path/to/dir # See the comment below the answer
rm -rv !(one|two)

PS: Do not use rm -f in a script.

PS: If /path/to/dir is coming from a variable, make sure that is is not empty before using it with cd:

if [ -z "${path_to_delete}" ] ; then
    "path_to_delete is empty! Aborting"
    exit 1
fi
cd "${path_to_delete}"
rm -rv !(one|two)
hek2mgl
  • 152,036
  • 28
  • 249
  • 266
  • 1
    And if you do `rm -r` in a file, **make sure you `cd` to the right directory first!** I have been bitten by that in the past. Thank $DIETY for tape backups – glenn jackman Dec 03 '18 at 15:58
  • Incredibly good point! Also if `/path/to/dir` comes from a variable, make sure that it is not empty before using it in the `rm` command. – hek2mgl Dec 03 '18 at 17:37
  • Maybe better to do `[ -z "${path_to_delete}" ] || [ ! -d "${path_to_delete}" ]` or just `cd "${path_to_delete}" || exit` – kvantour Dec 03 '18 at 17:43
  • 1
    The `! -d` check can be a good idea depending on the situation, but note that `cd ""` will leave the working directory unchanged and return `0` – hek2mgl Dec 03 '18 at 17:48