Skip to main content

Wildcards

In the File manipulations section, you learnt about a few commands to do interesting things. The problem was that they all operated on a single file at a time, which was not efficient. Now, you are going to learn a means to play about with a set of files at once.

Wildcards are a set of building blocks that allow you to create a pattern defining a set of files or directories. As you remember, whenever you refer to a file or directory on the command line, you are referring to a path. Whenever you refer to a path, you can also use wildcards in that path to turn it into a set of files or directories.

Here is the basic set of wildcards:

  • * represents zero or more characters
  • ? represents a single character
  • [] represents a range of characters

Basic case example

To illustrate the basic case, the * character is used. In the example below, every entry beginning with b is listed.

user@bash: pwd
/home/ryan/linuxtutorialwork
user@bash: ls
barry.txt blah.txt bob example.png firstfile foo1 foo2
foo3 frog.png secondfile thirdfile video.mpeg
user@bash: ls b*
barry.txt blah.txt bob
user@bash:

Under the hood

At first glance, you can assume that the command above (ls) receives the b* argument and proceeds to translate that into required matches. It is actually bash that does the translation for you. When you offer bash this command, it sees that you used wildcards. So before running the command (in this case, ls), it replaces the pattern with every file or directory (path) matching that pattern. You issue the following command:

ls b*

Then, the system translates this into the following:

user@bash: ls barry.txt blah.txt bob

Then, it executes the program. The program never sees the wildcards and has no idea that you used them. This is funky as it means you can use them on the command line whenever you want. You are not limited to only certain programs or situations.

Some more examples

For all examples below, assume you are in the linuxtutorialwork directory, and it contains the files listed above. Note that ls is used in these examples because it is a convenient way to illustrate wildcard usage. Otherwise, wildcards can be used with any command.

In this example, every file has the TXT extension, and an absolute path is used. Wildcards work just the same if the path is relative.

user@bash: ls /home/ryan/linuxtutorialwork/*.txt
/home/ryan/linuxtutorialwork/barry.txt /home/ryan/linuxtutorialwork/blah.txt
user@bash:

Now, let's introduce the ? operator. In this example, the search is for each file where the filename has i as the second letter. From the example above, you can also see that you can build the pattern using several wildcards.

user@bash: ls ?i*
firstfile video.mpeg
user@bash:

The following example is for the case when every file has a three-letter extension. Note that video.mpeg is not matched as the path name must match the given pattern exactly.

user@bash: ls *.???
barry.txt blah.txt example.png frog.png
user@bash:

For the final example, let's use the range operator ([ ]). Unlike the previous two wildcards that specified any character, the range operator allows you to limit the search to a subset of characters. In this example, the command looks for every file where the name begins with s or v.

user@bash: ls [sv]*
secondfile video.mpeg
user@bash:

With these ranges, you can also include a set by using a hyphen. For example, if you want to find every file where the name includes a digit, you can do the following:

user@bash: ls *[0-9]*
foo1 foo2 foo3
user@bash:

You can also reverse a range using the caret (^), which means look for any character, except for the ones specified.

user@bash: ls [^a-k]*
secondfile thirdfile video.mpeg
user@bash:

Real-world examples

The examples above illustrate how wildcards work. Here are a few examples to give you a taste of what you can do with wildcards in real world. Remember, these are just a small sample, and they can be used whenever you specify a path on the command line.

Find the file type of every file in a directory:

user@bash: file /home/ryan/*
bin: directory
Documents: directory
frog.png: PNG image data
public_html: directory
user@bash:

Move all files of either the JPG or PNG format (image files) into another directory.

user@bash: mv public_html/*.??g public_html/images/
user@bash:

Find out the size and modification time of the .bash_history file in every user's home directory. The .bash_history file keeps a history of the commands the user has entered on the command line. As you can see in this example, you can use wildcards at any point in the path.

user@bash: ls -lh /home/*/.bash_history
-rw------- 1 harry users 2.7K Jan 4 07:32 /home/harry/.bash_history
-rw------- 1 ryan users 3.1K Jun 12 21:16 /home/ryan/.bash_history
user@bash:

Activities for practicing

Let's play with some patterns:

  • A good directory to play with is /etc containing config files for the system. As a normal user, you can view the files, but you can't make any changes, so you can't do any harm. Do a listing of that directory to see what's there. Then, pick various subsets of files and see if you can create a pattern to select only those files.
  • Do a listing of /etc with only those files that contain an extension.
  • Use a three-letter extension.
  • Search for files whose name contains an uppercase letter. Hint: [[:upper:]] can be useful here.
  • List the files whose name is four characters long.