11

Having some trouble doing a copy in Bash. This works fine:

# Enable extended globbing and include filenames beginning with a '.'
shopt -s extglob dotglob
# Copy git repo to expected place
cp -r !($YOCTO_DIR) $POKY_DIR/$GIT_REPO_NAME/

But when I put an if statement round it:

if [ -z "$FROM_JENKINS" ]; then
    # FROM_JENKINS is blank, this is a local build

    # Enable extended globbing and include filenames beginning with a '.'
    shopt -s extglob dotglob
    # Copy git repo to expected place
    cp -r !($YOCTO_DIR) $POKY_DIR/$GIT_REPO_NAME/
fi

I get:

./build.sh: line 80: syntax error near unexpected token `('

Line 80 is the cp. If I remove the brackets it works:

    cp -r . $POKY_DIR/$GIT_REPO_NAME/

Why does the if statement not like brackets in cp?

3
  • 5
    Not related to your problem but you should quote all those variables. Commented Jun 13, 2023 at 0:26
  • Related: Which bash shell options are used by the parser? Commented Jun 13, 2023 at 8:04
  • @HaukeLaging, there's also the missing -- and failglob option. Commented Jun 13, 2023 at 8:09

1 Answer 1

19

The problem are the order and "range" of reading and executing.

The whole if block is just one command. So the shell has to read until the end of this command before it executes it.

That means that the rules WITHOUT shopt -s extglob dotglob (I am referring to the line here, not all of its content; as ilkkachu points out in the comment: the dotglob is not relevant for the problem) are valid until the end of the if block because the shopt is executed afterwards only. And without the shopt -s extglob the !( is illegal there.

So you have to move the shopt before the if (and may revert it in an else branch).

3
  • 2
    I think it's mostly about extglob, since it changes the way the shell syntax is parsed. dotglob takes effect even if set inside the block. shopt -u dotglob; if true; then shopt -s dotglob; echo *b*; fi finds the file .bbb Commented Jun 13, 2023 at 7:55
  • @ilkkachu I didn't put that well (just fixed that). The difference is that dotglob changes the execution of the code only but not the parsing. So the dotglob is read without being executed immediately, too. But that is fine as the echo needs it for globbing only, not for the command parsing so being executed after reading the whole block is fine. Commented Jun 13, 2023 at 21:12
  • 2
    Better yet, pick one set of options and shopt them all at the top of your script. Don't play games with turning extglob on and off all over the place. It just makes the script longer and harder to read. Commented Jun 13, 2023 at 23:33

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.