CS 160A - Using Wildcards

Objective: Learning about shell wildcards

Wildcards (which may also be called shell metacharacters, or, more accurately, globbing characters ) are special characters used in filename patterns. When the shell encounters a wildcard pattern on a command-line, it replaces it, if possible, with a list of paths that match the wildcard pattern.

Some notes on where to use Wildcards:

Wildcard Operators

The following sequences of characters are interpreted as wildcards by the shell. Enclosing characters in any type of quotes (single- or double-) hides them from the shell.

Operator Meaning Example Matches Objects Whose Names Are
* anything, including nothing A* capital A followed by any number (including zero) of any combination of characters
? a single character ??? exactly three characters long
a string of characters enclosed in [ ] a single character that is one of the characters enclosed in the brackets. [abc] a single character that is either a or b or c
two characters separated by a dash enclosed in [ ] one character whose value is greater than or equal to the first character and less than or equal to the second character [a-z] a single character whose value is greater than or equal to 'a' and less than or equal to 'z' . (i.e., a lowercase character) Note: uppercase characters have consecutive values, as do lowercase characters, as do digits. However, [a-Z] does not do what you want. Use [a-zA-Z] instead.
a character class enclosed in [ ] a single character that is a member of that character class [[:alpha:]]

the character class is alpha. It is indicated by [:alpha:] The inner brackets indicate the character class. The outer brackets indicate the character set (that it is a single character) Both sets of brackets are needed.

Classes include: alpha, upper, lower, digit, alnum, blank, space(whitespace), punct, print, ascii, cntrl, ascii | See Character Classes

if the first character inside of the [ ] is ! or ^ ! negates the character set. a single character that is not a member of the set. [^[:lower:]] a single character that is not a member of the character class [:lower:] Thus, any character that is not lowercase.

Note: * and ? will not match a leading . in a name (indicating a hidden file)

Note: ! is the traditional negation operator in character sets. ^ is also recognized by bash for this function to make it consistent with regular expressions, which we will cover later. We will use them interchangeably, but ^ is more important to know.

bash also offers brace expansion, which uses braces to enclose a comma-separated list of alternatives. Brace expansion is not a wildcard, as this sequence is expanded whether or not each possibility exists, rather it is a pattern generator:

Think through these wildcard expansions with the aid of the table above:

  1. [[:alpha:]]*

  2. [^012]?

  3. z*a?

  4. [0-9!a-z]*

  5. *a*z

  6. [[:alpha:]]

  7. *[^[:digit:][:punct:]]*

More Wildcard Exercises

Use the sample wildcard directory in our public workspace /pub/cs/grwoo/cs160a/wildcards

  1. Take the wildcard pattern from #2 and issue the following commands:
    • precede the wildcard with ls. It looks like ls understands wildcards.
    • precede the wildcard with echo. This shows that the shell expands wildcards.
    • precede the wildcard with echo ls. This shows that the shell expands the wildcard before it passes it to ls.
    • precede the wildcard with ls and put single quotes around the wildcard. This suppresses the shell's wildcard expansion and shows you that ls doesn't know anything about wildcards.
  2. Take the wildcard pattern from #3 and issue the following commands:
    • precede the wildcard with ls. Do the paths output seem to make sense?
    • precede the wildcard with echo. Can you reconcile the output with that using ls?
    • precede the wildcard with echo ls. This shows the command as it is executed.
    • Can you put the above together and come up with an explanation? Test your theory by using the command ls -dF followed by the wildcard. What do these options do?

    From this point on we will be practicing using wildcards with the ls command. As you just learned, it will be less confusing if you use the options -dF when using ls in the remainder of this exercise.

    Write commands to list objects in the current directory whose names

  3. are three characters long
  4. start with a letter, either upper-or lower-case
  5. contain a digit anywhere in the name
  6. end with a character that is not a digit
  7. contain a blank
  8. start with a .
  9. start with a . and are a total of three characters long
  10. contain at least one character that is neither a letter nor a digit
  11. contains a left or right square bracket [ or ]
  12. contain at least one instance of each of a and q in the name, in either order (you need two wildcards to do this!)

    Next, write commands to list objects whose paths are

  13. in a subdirectory of the current directory. The name of the object can be anything.
  14. in a subdirectory of the current directory whose name starts with a digit. The name of the object must be five characters long and start with a letter.

    Last, to show you that this really has nothing at all to do with ls:

  15. output the contents of all objects in the current directory whose name starts with a

Answers

The set of wildcards match anything in the current directory whose name

  1. Here are the commands that you should have used and some interpretation:
    • ls [^012]? - ls seems to understand wildcards (but it doesn't)
    • echo [^012]? - echo outputs the list of names that match the pattern!
    • echo ls [^012]? - echo outputs what an ls command looks like after the shell has expanded the wildcard. Are there any wildcards left for ls to worry about?
  2. Here are the commands that you should have used and some interpretation:
    • ls z*a? - ls outputs names, but they don't appear to match the pattern!
    • echo z*a? - echo outputs the list of names that match the pattern!
    • echo ls z*a? - echo outputs what an ls command looks like after the shell has expanded the wildcard. If this is the command as it is executed, why does ls put out strange names?
    • adding the options -dF shows that the object that matches the wildcard is a directory. Remember that ls outputs the contents of the directory by default. The -d suppresses this behavior and the -F puts the / at the end to indicate the directory.
  3. ls -dF ???
  4. ls -dF [a-zA-Z]*            # or [[:alpha:]]*
  5. ls -dF *[0-9]*              # or *[[:digit:]]*
  6. ls -dF *[^0-9]             # or *[^[:digit:]]
  7. ls -dF *''*                  # Note you must use quotes to 'hide' the blank OR
    ls -df *\ *                    # use a backslash before the blank. You can also use the
    ls -dF *[[:blank:]]*         # :blank: class. Careful, *[' ']* or *[\ ]* do not work!
  8. ls -dF .*
  9. ls -dF .??                  # Why did this file not appear in the output of #8?
  10. ls -dF *[^a-zA-Z0-9]*               # can you do this using character classes?
  11. ls -dF *[][]*           # a character set containing the characters [ and ]
  12. ls -dF *a*q* *q*a*
  13. ls -dF */*
  14. ls -dF [0-9]*/[a-zA-Z]???? # or [[:digit:]]*/[[:alpha:]]????
  15. cat a*

For the original version of these materials, see Greg Boyd's Exercises Wildcards