VMware ESXi and vSphere Cluster Management

Linux Wildcards: Shell Globbing with *, ?, and Brackets

Learn how Linux shell wildcards such as *, ?, and bracket expressions select filenames, expand in commands, and can be used safely.

What Linux wildcards do

A wildcard is a special pattern symbol that helps select matching filenames and pathnames. In Linux shells, these patterns are commonly called globs.

Before a command such as ls, cp, mv, or rm runs, the shell usually performs pathname expansion: it replaces a matching pattern with the matching filenames. The command then receives those filenames as separate arguments.

ls -- *.txt

If the current directory contains notes.txt and todo.txt, the shell effectively runs:

ls -- notes.txt todo.txt

Shell globs are different from regular expressions. Both are pattern languages, but their syntax and purpose differ. A shell glob selects pathnames, while a regular expression is commonly used to search or validate text with tools such as grep.

Core Linux wildcard symbols

Pattern symbolMeaningCharacters matchedExample patternExample matching names
?Matches exactly one characterOne character in one filename componentO??dOind, Okhd
*Matches zero or more charactersAny number of characters, including noneO*dOd, Oad, Oereed
[abc]Matches one listed characterExactly one character from the listO[ac]dOad, Ocd
[a-e]Matches one character in a rangeExactly one character from a through eO[a-e]dOad, Obd, Oed
[!abc]Matches one character not listedExactly one character other than a, b, or cO[!a]dObd, Odd

The question-mark wildcard: ?

The question mark matches exactly one character in a filename component. It is useful when a name has a fixed length or a fixed number of unknown positions.

O??d

This pattern requires a name to begin with O, end with d, and contain exactly two characters between them.

  • Matches: Oind, Okhd, Oerd
  • Does not match: Od, because it has no characters between O and d
  • Does not match: Oad, because it has only one middle character
  • Does not match: Oereed, because it has more than two middle characters

Each ? accounts for one character. Therefore, three question marks would require exactly three characters in that position.

The asterisk wildcard: *

The asterisk matches zero or more characters. Unlike ?, it can match text of varying lengths, including an empty section.

O*d

This matches names beginning with O and ending with d, regardless of how many characters appear in the middle.

  • Od matches because * can match zero characters.
  • Oad matches because * can match a.
  • Oind matches because * can match in.
  • Oereed matches because * can match eree.

Common uses include prefixes, suffixes, and extensions:

backup*       # names beginning with backup
*.txt # names ending with .txt
report*.log # names beginning with report and ending with .log

A glob can contain more than one asterisk, such as 2026-*-backup.*. Each asterisk matches within its own filename component.

Bracket expressions

A bracket expression selects exactly one character from a set or range. It is written inside square brackets.

Character lists

O[ac]d

This matches Oad and Ocd. The bracket expression occupies one position, so it does not match Obd or Oaard.

Character ranges

O[a-e]d

The range a-e represents a, b, c, d, or e. The pattern matches:

  • Oad
  • Obd
  • Ocd
  • Odd
  • Oed

Other examples include [0-9] for one digit and [A-Z] for one uppercase letter. A range selects one position; it does not behave like *.

Negated bracket expressions

A bracket expression can exclude characters. In many shells, [!a] means one character other than a. Some shells also accept [^a] for the same purpose. The ! form is generally the more portable shell spelling, but check the shell's documentation when portability matters.

[!a]*

This selects visible names whose first character is not a, followed by zero or more additional characters.

Comparing similar patterns

PatternExpected matchesExpected non-matchesReason
O??dOind, Okhd, OerdOd, Oad, OereedEach question mark matches exactly one character.
O*dOd, Oad, Oind, OereedA name not beginning with O or not ending with dThe asterisk matches zero or more characters.
O[ac]dOad, OcdObd, OaardThe bracket list allows one character, either a or c.
O[a-e]dOad, Obd, Ocd, Odd, OedOfd, OabdThe range allows one character from a through e.

Practicing in an isolated directory

Use a test directory so experiments do not affect important files.

mkdir -p wildcard-practice && cd wildcard-practice
touch Od Oad Ocd Obd Oind Okhd Oerd Oereed notes.txt report1.log report2.log .hidden

Preview the results of several patterns:

printf '%s\n' -- O??d
printf '%s\n' -- O*d
printf '%s\n' -- O[ac]d
printf '%s\n' -- O[a-e]d

The shell expands each unquoted pattern before printf receives it. The -- argument is a conventional separator that helps distinguish data from options in commands that support it.

Using globs with commands

Inspecting files with ls

ls -- *.txt
ls -- backup*
ls -d -- .*

The first command lists visible text files. The second lists visible names beginning with backup. The explicit dot pattern in the third command selects dot-prefixed entries, but it can also include . and ..; handle its output carefully.

Copying and moving

cp -- *.txt ../text-backups/
mv -- report?.log archived/

If a pattern expands to several names, cp or mv receives all of them. For a multi-source operation, the destination normally must be a directory.

Removing files

rm -- *.tmp

Preview first:

printf '%s\n' -- *.tmp
ls -l -- *.tmp
rm -- *.tmp

Important globbing behavior

A glob does not cross a slash

Normal wildcard matching occurs within one directory-name component. An asterisk does not normally cross a slash.

*.txt

This selects text files in the current directory, not text files inside every subdirectory. A pattern such as logs/* selects entries directly inside logs, but not entries in deeper directories. Recursive selection requires another tool or shell feature, such as an appropriately constructed find command.

Hidden names are normally excluded

A hidden file is a Unix filename beginning with a period. Patterns that do not begin with a period normally do not match such names. Thus, * normally excludes .hidden.

To explicitly select ordinary hidden entries, use a pattern beginning with a dot:

ls -d -- .*

Because this can include . and .., use it with care. In Bash, shopt -s dotglob changes glob behavior so many ordinary globs can include dot-prefixed names. Shell options differ, so verify the behavior before using a modifying command.

When nothing matches

In many shells, an unmatched pattern is passed to the command unchanged. For example, if no file ends in .csv, printf '%s\n' -- *.csv may print the literal text *.csv. A command such as ls -- *.csv may instead report that a file named *.csv does not exist.

Bash can be configured with:

shopt -s nullglob

With Bash's nullglob option, an unmatched pattern expands to zero arguments. This can be useful in scripts, but scripts must still handle the possibility that a command receives no filenames.

Quoting and escaping

Quoting preserves characters as literal text. Single and double quotes suppress pathname expansion:

ls -- '*.txt'

This asks ls to look for a literal filename named *.txt; it does not select all text files. A backslash is an escape that makes the following special character literal:

printf '%s\n' 'file*name' file\*name

Both arguments retain the asterisk rather than expanding it. Leave a glob unquoted when you want the shell to expand it, and quote literal text or variable expansions when needed.

Safe wildcard usage checklist

SituationRecommended actionExample
Previewing matchesUse printf or ls before changing files.printf '%s\n' -- *.tmp
No files matchCheck the directory and pattern; decide whether shell options such as Bash's nullglob are appropriate.pwd, ls, shopt -s nullglob
Filenames beginning with -Place -- before expanded filenames when the command supports it.rm -- --strange-name or rm -- *.tmp
Hidden filesUse an explicit dot pattern and remember that .* may include . and ...ls -d -- .*
Removing filesPreview the exact expansion, then use the narrowest safe pattern.ls -l -- *.tmp followed by rm -- *.tmp

Troubleshooting wildcard problems

The command displays the pattern itself

The pattern may not match anything, or it may have been quoted or escaped.

  1. Check the current directory with pwd.
  2. List available names with ls.
  3. Inspect the command's pattern with printf '%s\n' -- pattern.
  4. Remove unintended quotes or backslashes only if expansion is desired.

A hidden file is missing

This is normal for a pattern such as *. Use an explicit pattern beginning with a period, or enable the relevant shell option with care.

A pattern matches too many files

The * operator allows an empty sequence and any number of characters. Replace it with ? for fixed positions or a bracket expression for restricted choices. Always preview the result.

Quotes prevent expansion

Single and double quotes suppress pathname expansion. Leave the intended glob unquoted, but continue to quote unrelated literal text and variable values appropriately.

A filename is interpreted as an option

A matched name beginning with - may be mistaken for a command option. Put -- before the expanded names, for example rm -- pattern.

Regular-expression syntax does not work

Shell globs and regular expressions are separate languages. Use glob syntax for shell pathname selection, and use the syntax documented by grep or another text-processing tool when matching file contents.

Exam-relevant points

  • ? matches exactly one character.
  • * matches zero or more characters.
  • A bracket expression matches one character from a list or range.
  • Globbing normally happens in the shell before the command runs.
  • Globs do not normally cross slashes.
  • Patterns not beginning with a period normally exclude hidden names.
  • Quoted or escaped wildcard symbols remain literal.
  • An unmatched pattern may remain unchanged, depending on the shell and its options.
  • One pattern can expand to many filenames, so preview it before using rm, mv, or another modifying command.

For related pattern languages, see shell quoting, escaping, and filename pattern matching.