bash-hackers-wiki/docs/syntax/expansion/globs.md
Hanson Char b75c3a588b Fix hyperlinks of markdown pages at depth 3
find docs/ -depth 3  -name '*.md' | xargs grep '(.*/' -l | \
  xargs -I{} \
  sed -i '' \
  -e 's%(/\([^/#).][^/#).]*\)/\([^/#).][^/#).]*\)\(.md\)\{0\})%(../../\1/\2.md)%g' \
  -e 's%(/\([^/#).][^/#).]*\)/\([^/#).][^/#).]*\)#\([a-zA-Z_-][0-9a-zA-Z_-]*\))%(../../\1/\2.md#\3)%g' \
  -e 's%(/\([^/#).][^/#).]*\)/\([^/#).][^/#).]*\)/\([^/#).][^/#).]*\)\(.md\)\{0\})%(../../\1/\2/\3.md)%g' \
  -e 's%(/\([^/#).][^/#).]*\)/\([^/#).][^/#).]*\)/\([^/#).][^/#).]*\)#\([a-zA-Z_-][0-9a-zA-Z_-]*\))%(../../\1/\2/\3.md#\4)%g' \
  -e 's%](\([^:.>)#][^:.>)#]*\))%](../../\1.md)%g' \
  -e 's%](\([^:.>)#][^:.>)#]*\)#\([^:.>)#][^:.>)#]*\))%](../../\1.md#\2)%g' \
  {}

Related to https://github.com/flokoe/bash-hackers-wiki/issues/10
2024-01-28 17:26:57 -08:00

115 lines
4.3 KiB
Markdown

# Pathname expansion (globbing)
## General
Unlike on other platforms you may have seen, on UNIX(r), the shell is
responsible for interpreting and expanding globs (\"filename
wildcards\"). A called program will never see the glob itself; it will
only see the expanded filenames as its arguments (here, all filenames
matching `*.log`):
grep "changes:" *.log
The base syntax for the pathname expansion is the [pattern
matching](../../syntax/pattern.md) syntax. The pattern you describe is matched
against all existing filenames and the matching ones are substituted.
Since this substitution happens **after [word
splitting](../../syntax/expansion/wordsplit.md)**, all resulting filenames are
literal and treated as separate words, no matter how many spaces or
other `IFS`-characters they contain.
## Normal behaviour
- with [the set command](../../commands/builtin/set.md) (`-f`, `noglob`) you
can entirely disable pathname expansion
- when matching a pathname, the slash-character (`/`) always needs to
be matched explicitly
- the dot at the beginning of a filename must be matched explicitly
(also one following a `/` in the glob)
- a glob that doesn\'t match a filename is unchanged and remains what
it is
## Customization
- when the shell option `nullglob` is set, non-matching globs are
removed, rather than preserved
- when the shell option `failglob` is set, non-matching globs produce
an error message and the current command is not executed
- when the shell option `nocaseglob` is set, the match is performed
case-insensitive
- when the shell option `dotglob` is set, wildcard-characters can
match a dot at the beginning of a filename
- when the shell option `dirspell` is set, Bash performs spelling
corrections when matching directory names
- when the shell option `globstar` is set, the glob `**` will
recursively match all files and directories. This glob isn\'t
\"configurable\", i.e. you **can\'t** do something like `**.c` to
recursively get all `*.c` filenames.
- when the shell option `globasciiranges` is set, the bracket-range
globs (e.g. `[A-Z]`) use C locale order rather than the configured
locale\'s order (i.e. `ABC...abc...` instead of e.g. `AaBbCc...`) -
since 4.3-alpha
- the variable [GLOBIGNORE](../../syntax/shellvars.md#GLOBIGNORE) can be set
to a colon-separated list of patterns to be removed from the list
before it is returned
### nullglob
Normally, when no glob specified matches an existing filename, no
pathname expansion is performed, and the globs are [**not**]{.underline}
removed:
$ echo "Textfiles here:" *.txt
Textfiles here: *.txt
In this example, no files matched the pattern, so the glob was left
intact (a literal asterisk, followed by dot-txt).
This can be very annoying, for example when you drive a
[for-loop](../../syntax/ccmd/classic_for.md) using the pathname expansion:
for filename in *.txt; do
echo "=== BEGIN: $filename ==="
cat "$filename"
echo "=== END: $filename ==="
done
When no file name matches the glob, the loop will not only output stupid
text (\"`BEGIN: *.txt`\"), but also will make the `cat`-command fail
with an error, since no file named `*.txt` exists.
Now, when the shell option `nullglob` is set, Bash will remove the
entire glob from the command line. In case of the for-loop here, not
even one iteration will be done. It just won\'t run.
So in our first example:
$ shopt -s nullglob
$ echo "Textfiles here:" *.txt
Textfiles here:
and the glob is gone.
### Glob characters
- \* - means \'match any number of characters\'. \'/\' is not matched
(and depending on your settings, things like \'.\' may or may not be
matched, see above)
- ? - means \'match any single character\'
- \[abc\] - match any of the characters listed. This syntax also
supports ranges, like \[0-9\]
For example, to match something beginning with either \'S\' or \'K\'
followed by two numbers, followed by at least 3 more characters:
[SK][0-9][0-9]???*
## See also
- [Introduction to expansion and
substitution](../../syntax/expansion/intro.md)
- [pattern matching syntax](../../syntax/pattern.md)
- [the set builtin command](../../commands/builtin/set.md)
- [the shopt builtin command](../../commands/builtin/shopt.md)
- [list of shell options](../../internals/shell_options.md)