0

Below is my script placed in /usr/bin as I want to make it available globally

#!/bin/bash
cd /app/data/zips
rm -rf -i -v !(*.zip)
cd /app/cronscripts/import
> import_output.log
nohup ./import.sh > import_output.log & disown

Everything in the above script is working perfectly fine apart from the below-given line, however, this command is working perfectly fine when running it from the terminal directly. It's for deleting all files and folders except .zip files in the directory

rm -rf -i -v !(*.zip)

Whenever I try to run this script it gives me the following error.

/usr/bin/importdata.sh: line 3: syntax error near unexpected token `('
/usr/bin/importdata.sh: line 3: `rm -rf -i -v !(*.zip)'

My which bash output is:

/bin/bash

OS information:

Distributor ID: Ubuntu
Description:    Ubuntu 18.04.3 LTS
Release:        18.04
Codename:       bionic
9
  • If I were you I'd just do a find /app/data/zips -depth \! -name "*.zip" -exec rm -rf -i -v '{}' +. Commented Jun 1, 2020 at 1:06
  • How do you run your script ? It's like you ran it with sh script.sh instead of using bash Commented Jun 1, 2020 at 1:07
  • This is to replace the first two lines after the line with #!/bin/bash. What it does is find all files or directories in /app/data/zips that do NOT (the !) have the name *.zip and perform on them the action of rm .... Commented Jun 1, 2020 at 1:10
  • 1
    Anytime you use cd in a script, you need some sort of error checking on it -- if the cd fails for some reason, the rest of the script will execute in the wrong place, with potentially dangerous results. Suppose that rm command ran in the wrong place! Commented Jun 1, 2020 at 2:04
  • 1
    @AbdulMoiz Personally, I prefer not to cd in scripts at all; instead, use explicit paths, like rm -rf -i -v /app/data/zips/!(*.zip), > /app/cronscripts/import/import_output.log, etc. When I need to cd, I like to use something like cd /somedir || { echo "Error changing directory" >&2; exit 1; } (see BashPitfalls #19). BTW, shellcheck.net is good at pointing out common mistakes like this. Commented Jun 1, 2020 at 3:55

1 Answer 1

5

In bash, !(pattern) is an extended glob pattern. Turn on the shell option which enables that:

shopt -s extglob

shopt should appear on its own line at the start of the script, along with any other options which you may be relying on. See wooledge: https://mywiki.wooledge.org/glob#Options_which_change_globbing_behavior

extglob changes the way certain characters are parsed. It is necessary to have a newline (not just a semicolon) between shopt -s extglob and any subsequent commands to use it. You cannot enable extended globs inside a group command that uses them, because the entire block is parsed before the shopt is evaluated.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.