Glob options let Bash decide how wildcard patterns behave before a command receives its arguments. They matter when a script must handle empty match sets, hidden files, or nested directories without accidentally processing a literal pattern such as empty/*.log.
Bash controls these behaviors with the shopt builtin. By default, an unmatched glob stays as literal text; nullglob removes it, dotglob lets a wildcard match names beginning with a dot, and globstar makes ** walk into subdirectories. Use failglob instead of nullglob when an unmatched pattern should stop the command with an error.
Set glob options close to the array assignment or loop that needs them. The setting belongs to the current shell process, so a script started with bash script.sh exits with its option state, while options enabled in an interactive shell remain active until shopt -u disables them.
Related: How to loop over files in Bash
Related: How to create and run a Bash script
$ mkdir -p reports/archive empty $ printf 'app\n' > reports/app.log $ printf 'db\n' > reports/archive/db.log $ printf 'hidden\n' > reports/.hidden.log $ printf 'note\n' > reports/readme.txt
#!/usr/bin/env bash set -euo pipefail without_null=(empty/*.log) printf "without nullglob:\n" printf "count=%s\n" "${#without_null[@]}" printf "value=%s\n" "${without_null[0]}" shopt -s nullglob with_null=(empty/*.log) printf "with nullglob:\n" printf "count=%s\n" "${#with_null[@]}" shopt -s dotglob dot_matches=(reports/*.log) printf "with dotglob:\n" printf "%s\n" "${dot_matches[@]}" shopt -s globstar recursive_matches=(reports/**/*.log) printf "with globstar:\n" printf "%s\n" "${recursive_matches[@]}"
Set options before assigning a glob to an array or starting a loop. Bash expands the pattern at that point, not later when the value is printed.
$ bash -n glob-options-demo.sh
No output means Bash did not find a parse error.
$ bash glob-options-demo.sh without nullglob: count=1 value=empty/*.log with nullglob: count=0 with dotglob: reports/.hidden.log reports/app.log with globstar: reports/.hidden.log reports/app.log reports/archive/db.log
$ shopt -u nullglob dotglob globstar
A script run with bash glob-options-demo.sh exits with its own option state, so this cleanup is only needed after interactive testing.
$ rm -rf glob-options-demo.sh reports empty