bash extglob pattern matching breaks when enclosed in a function

316 Views Asked by At

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?

1

There are 1 best solutions below

0
On

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