How To Use Unix Wildcards

How To Use Unix Wildcards

Wildcard characters in Unix/Linux allow the matching of files in an abstracted way. Rather than having to perfectly match a file or directory’s exact name and casing, you can insert wildcards to allow variations and match multiple files. Using wildcards to match multiple files is known as filename expansion, or "globbing" in some shells (like Bash).

Wildcards can be used in almost any Linux/Unix command or utility that accepts multiple file parameters. From [.inline-code]ls[.inline-code] to [.inline-code]pandoc[.inline-code], you can use wildcards to operate on files in batches without having to create extensive file lists.

[#the-two-wildcard-chars]Asterisk (*) and question mark (?) are the two wildcard characters[#the-two-wildcard-chars]

Both of these will match any character (including spaces, punctuation, and non-UTF symbols). The asterisk matches any number of characters (including zero), and the question mark matches exactly one character.

If you have a directory with files named [.inline-code]myfile-1.txt[.inline-code], [.inline-code]myfile-2.txt[.inline-code], and [.inline-code]myfile-3.txt[.inline-code], then you can match all three of these files with the wildcard expression [.inline-code]myfile-?.txt[.inline-code]. This would exclude [.inline-code]myfile-10.txt[.inline-code], though, as there is more than one character in [.inline-code]10[.inline-code], so the single question mark wildcard would fail to match. If you wanted both [.inline-code]myfile-1.txt[.inline-code] and [.inline-code]myfile-10.txt[.inline-code] to be matched, you would want to use [.inline-code]myfile-*.txt[.inline-code].

[#examples]Examples of commands with wildcards[#examples]

[#asterisk-any-number-chars]An asterisk (*) matches any number of characters: [.inline-code]ls b*[.inline-code][#asterisk-any-number-chars]

[#asterisk-zero-chars]An asterisk also matches zero characters (a.txt): [.inline-code]ls a*.txt[.inline-code][#asterisk-zero-chars]

[#refine-results-with-extension]Refine results by including an extension, matching only files with a matching extension: [.inline-code]ls b*.txt[.inline-code][#refine-results-with-extension]

[#question-mark-matches-single-char]A question mark matches a single character: [.inline-code]b-1?.txt[.inline-code][#question-mark-matches-single-char]

[#question-mark-requires-char]A question mark requires a character (a.txt is not matched): [.inline-code]ls a?.txt[.inline-code][#question-mark-requires-char]

[#square-bracket-multiple-chars-or-range]Square brackets match multiple characters or a range in most shells (demo in Bash): [.inline-code]ls b-[12]?.*[.inline-code][#square-bracket-multiple-chars-or-range]

[#wildcards-to-find-files-matching-text]Use wildcards to find files with matching text in the middle of the filename[#wildcards-to-find-files-matching-text]

You can find files with matching text in the middle of the filename by beginning and ending with an asterisk, e.g. [.inline-code]*keyword*[.inline-code]. This will match files that start with any number of characters, followed by [.inline-code]keyword[.inline-code], and ending with any number of characters. Unless you specify a file extension, all file extensions will be included. For example:

The command [.inline-code]find ~/Dropbox -name '*conflicted copy*'[.inline-code] will return all of your conflicted Dropbox copies by matching anything containing "conflicted copy," regardless of what machine name generated the conflict. You can combine this with an [.inline-code]-exec rm[.inline-code] to clear out all of those conflicts.

[#matching-subdirectories-stars]Matching subdirectories with [.inline-code]**[.inline-code][#matching-subdirectories-stars]

You can match files in multiple subdirectories by including [.inline-code]**[.inline-code] in the wildcard match. For example, if you wanted to find all [.inline-code].txt[.inline-code] files in all subdirectories of the current directory, you could run [.inline-code]ls **/*.txt[.inline-code]. In some shells, this will only search subdirectories, so you would have to combine it with [.inline-code]*.txt[.inline-code] if you also wanted to include [.inline-code].txt[.inline-code] files in the current directory. For the most part, though, using [.inline-code]**/*.txt[.inline-code] will include all [.inline-code].txt[.inline-code] files in the current directory as well as in subdirectories.

[#square-brackets-specific-characters]Use square brackets ([]) to match more specific characters[#square-brackets-specific-characters]

There are also square bracket operators in most shells (notably not Fish). These allow you to define a specific character set to match, e.g. [.inline-code]myfile-[0-2].txt[.inline-code]. That would match [.inline-code]myfile-1.txt[.inline-code] and [.inline-code]myfile-2.txt[.inline-code], but not [.inline-code]myfile-3.txt[.inline-code] or [.inline-code]myfile-10.txt[.inline-code]. Square bracket operators can give you more granular matching than [.inline-code]*[.inline-code] or [.inline-code]?[.inline-code]. Note that a square bracket expression can only match a single character; unlike regular expressions, there's no repeat operator. Square brackets can contain a list of individual characters that are matched, e.g. [.inline-code][adg][.inline-code] to match [.inline-code]a[.inline-code], [.inline-code]d[.inline-code], or [.inline-code]g[.inline-code], or a range of numbers or letters to allow, specified with a hyphen between two characters. Matching is case-sensitive, so if you want to match any letter between [.inline-code]a[.inline-code] and [.inline-code]z[.inline-code] regardless of case, your expression would be [.inline-code][a-zA-Z][.inline-code]. To replicate the [.inline-code]*[.inline-code] operator but exclude any non-alphanumeric characters, use [.inline-code][a-zA-Z0-9][.inline-code].