How to pass ext glob into bash script from sh and then expand it

I have script se.sh:

#!/bin/bash

files="$1"

shopt -s nullglob
shopt -s extglob
for f in a/path/to/all/files/${files}; do
  echo "file process:${f}"
done
shopt -u nullglob
shopt -u extglob

When I run:./se.sh "a*.txt", it will process the correct files in the folder.
When I run ./se.sh "{a,1}*.txt", I want process files started with a*.txt or 1*.txt, but it didn’t run as I expected.

I have searched for quite a while, see

bash-loop-over-file,

using-a-glob-expression-passed-as-a-bash-script-argument,

how-to-pass-a-globbing-pattern-as-parameter-to-a-function-in-bash

  • 2

    {a,1} is not an extglob, it is braces expansion. If you want extglob @(a|1)*.txt use extglob.

    – 




  • To expand on KamilCuk’s answer, look at the order of shell expansions — brace expansion happens before parameter expansion. You’ll need eval if you want to expand braces stored in a variable.

    – 




  • You can also use the standard glob [a1]*.txt instead of that particular brace expansion.

    – 

Not an answer. Quick demo of my comment:

$ ls
config.json  example.tcl  tests.toml
$ files="{e,t}*"
$ echo "$files"
{e,t}*
$ declare -a x=( "$files" )
$ declare -p x
declare -a x=([0]="{e,t}*")
$ eval declare -a x=( "$files" )
$ declare -p x
declare -a x=([0]="example.tcl" [1]="tests.toml")

Of course, you don’t want to blindly eval any user input without thorough validation.

Leave a Comment