Shell Pattern Explained with Shell Script Examples

The following was quoted from : Shell Pattern Matching, I will try to explain the details by adding inline comment with actual shell script examples by myself.

Shell Pattern Matching

find and locate can compare file names, or parts of file names, to shell patterns. A shell pattern is a string that may contain the following special characters, which are known as wildcards or metacharacters.

You must quote patterns that contain metacharacters to prevent the shell from expanding them itself. Double and single quotes both work; so does escaping with a backslash.

Inline Explain Begin This means that the pattern string must be quoted and passed to the command (e.g., find) before the shell try to expand it by itself. So for example, say our current folder contains two files abc.txt and abbc.txt: and we expect to see the result of both abc.txt and abbc.txt by the pattern ab* but if we do not quote the pattern ab* in the find command:

$ find -name ab*

it will report error:

find: paths must precede expression: abc.txt  
Usage: find \[-H\] \[-L\] \[-P\] \[-Olevel\] \[-D help|tree|search|stat|rates|opt|exec\] \[path...\] [expression]

This is because, the shell (e.g., bash) expand ab* before it folk a process to execute find, so what actually passed to find becomes:

$ find -name abbc.txt abc.txt

which causes find to report error.

And the document already gives us the three solutions to fix it: single quotes, double quotes, or backslash:

$ find -name 'ab*'  
$ find -name "ab*"
$ find -name ab\*

The above three commands reports the same correct result:

./abbc.txt  
./abc.txt

You might also want to check this post for further references: Difference Between Single and Double Quotes in Bash Inline Explain End

`*`    

    Matches any zero or more characters. 

Inline Explain Begin  Note the difference between regular expression pattern here, when it comes to regular expression, we use ‘.*’ to match any zero or more characters where the period character denote any one character and the start character denote zero or more of the preceding character. However, here the period symbol (‘.’) is just a normal character as say ‘a’ is. Suppose the current directory contains two files named as .git and tgit, then the output of the following command:

$ find -name '.git'

is

 
 ./.git

and the output of the following command is different:

find -name '*git'

is

./tgit
./.git

This fact is also explained as in the following paragraph (1).  Inline Explain End

`?`

    Matches any one character. 

Inline Explain Begin  Note the difference between regular expression pattern again, as already mentioned, ‘.’ (the period symbol) denotes any one character in regular expression and the question symbol (‘?’) in regular expression pattern is only a quantifier.  Inline Explain End.

[string]: 

Matches exactly one character that is a member of the string string. This is called a character class. As a shorthand, stringmay contain ranges, which consist of two characters with a dash between them. For example, the class [a-z0-9_] matches a lowercase letter, a number, or an underscore. You can negate a class by placing a ‘!’ or ‘^’ immediately after the opening bracket. Thus, ‘[^A-Z@]’ matches any character except an uppercase letter or an at sign.

\

    Removes the special meaning of the character that follows it. This works even in character classes.

In the find tests that do shell pattern matching (‘-name’, ‘-wholename’, etc.), wildcards in the pattern will match a ‘.’ at the beginning of a file name. This is also the case for locate. Thus, ‘find -name ‘*macs’’ will match a file named .emacs, as will ‘locate ‘*macs’’. —— (1)

Slash characters have no special significance in the shell pattern matching that find and locate do, unlike in the shell, in which wildcards do not match them. Therefore, a pattern ‘foo*bar’ can match a file name ‘foo3/bar’, and a pattern ‘./sr*sc’ can match a file name ‘./src/misc’.

If you want to locate some files with the ‘locate’ command but don’t need to see the full list you can use the ‘–limit’ option to see just a small number of results, or the ‘–count’ option to display only the total number of matches.

Written on August 16, 2015