B H
B H

Reputation: 131

bash extglob pattern matching breaks when enclosed in a function

This works

shopt -s extglob
find /usr/!(^*|@*) -maxdepth 0 -cmin +1 -exec echo {} \;
shopt -u extglob

This returns an error

syntax error near unexpected token `('

function test {
  shopt -s extglob
  find /usr/!(^*|@*) -maxdepth 0 -cmin +1 -exec echo {} \;
  shopt -u extglob
}

test

What am I missing, that would permit me to use this in a function?

Upvotes: 1

Views: 370

Answers (1)

choroba
choroba

Reputation: 242133

The problem is bash needs extglob to be turned on at two times:

  1. when parsing the script

  2. when executing the actual command

By including the shopt into the function body, 1. is not satisified. If you broaden the scope of the shopt to include the function declaration, too, bash will parse the function correctly, but it will fail when running it (i.e. 2. is not satisfied):

shopt -s extglob
function test {
    find /usr/!(^*|@*) -maxdepth 0 -cmin +1 -exec echo {} \;
}
shopt -u extglob

The error:

find: ‘/usr/!(^*|@*)’: No such file or directory

So, just turn shopt extglob on at the beginning of the script and that's it. Or, if you really need it to be off elsewhere, turn it on and off both inside and outside the function:

#! /bin/bash
shopt -s extglob
function test {
    shopt -s extglob
    find /usr/!(^*|@*) -maxdepth 0 -cmin +1 -exec echo {} \;
    shopt -u extglob
}
shopt -u extglob

test

Upvotes: 4

Related Questions