You'll get your Mac news here from now on...

Help TMO Grow

Subscriber Login

Advertising Info


The Mac Observer Express Daily Newsletter


More Info

Site Navigation

Home
News
Tips
Columns & Editorials
Reviews
Reports
Archives
Search
Forums
Links
Mac Links
Software
Reports
Contact

Mac OS X Command Line 101
by Richard Burton


Understanding Metacharacters
Part III of this series...
May 10th, 2002

"Well, I never metacharacter I didn't like."
- Ron Wurtz (a friend from grad school, you don't know him)

This series is designed to help you learn more about the Mac OS X command line. If you have any questions about what you read here, check out the earlier columns, write back in the comments below, or join us in Hardcore X! forum.

[Editor's Note: This installment was originally supposed to have been published as Part IV of this series, due to an error on TMO's part. It should be read after Part IV, The Missing Argument Chapter, which has been published early for those working along with the series.]

In the previous column, we looked at arguments and options, using the cd and ls commands to show commands requiring and responding to different numbers and types of arguments. While the ability to manipulate the commands with different arguments is handy, it only hinted at the power at your fingertips.

The Unix shells have a set of special characters known as 'metacharacters'. We have run into these before. In our first discussion, involving the tcsh prompt and the cd command, it was noted that the tilde character, '~', is a shorthand for 'my home directory'. What is really means is 'the home directory of the user following me'; however, if there is no user, it defaults to your home directory.

    [localhost:~] dr_unix% pwd
    /Users/dr_unix
    [localhost:~] dr_unix% cd ~
    [localhost:~] dr_unix% pwd
    /Users/dr_unix
    [localhost:~] dr_unix% cd ~root
    [localhost:~root] dr_unix% pwd
    /private/var/root
    [localhost:~root] dr_unix% cd ~fred
    Unknown user: fred.
    [localhost:~root] dr_unix% cd ~
    [localhost:~] dr_unix% pwd
    /Users/dr_unix
    [localhost:~] dr_unix% 
    

Here, when we type cd ~, the '~' is expanded to our current home directory, /Users/dr_unix, before the command is passed to the system. The shell takes the cd ~root command, determines that the home directory for root is '/private/var/root', then passes the command cd /private/var/root to the system. Likewise, for the command cd ~fred, the shell cannot find a user 'fred' on the system, so it prints the error message (Unknown user: fred.) and does not change directory.

'~' is part of a special class of characters called 'filename metacharacters'. The shell interprets them differently than a regular old character (like, say, a 'b' or an 'N'). As we've seen, in the case of '~', the shell will expand these characters behind the scenes, in a way that depends on which character is to be expanded. The filename metacharacters are: *: Used to match any number of any characters
?: Used to match exactly one of any character
~: Your home directory
~name: Home directory of the user "name"
[abc]: Used to match any one of the characters in the square brackets (in this case, either an 'a', a 'b', or a 'c'). A dash (-) can be used to denote a range, like [A-M].
{abc,def,ghi}: Expand each comma-seperated string inside the braces.
Let's use ls to show how this works. Because '*' can denote any number of any characters, the command ls * is the same as ls if there are no directories to be listed.

    [localhost:~] dr_unix% ls
    Adam.txt   Documents  Movies     Pictures   Sites      temp.html  who_list
    Desktop    Library    Music      Public     personal   test_1.txt
    [localhost:~] dr_unix% ls *
    Adam.txt   temp.html  test_1.txt who_list
    
    Desktop:
    
    Documents:
    6197.txt                                Movie_1
    Acrobat User Data                       fw9.pdf
    AppleWorks User Data                    iTunes
    
    Library:
    Addresses                 FontCollections           Preferences
    Application Support       Fonts                     Printers
    Assistants                Internet Plug-Ins         Screen Savers
    Audio                     Internet Search Sites     Sounds
    Caches                    Keyboards                 Speech
    ColorPickers              Keychains                 Voices
    Documentation             Logs                      iTunes
    Favorites                 Mail
    
    Movies:
    
    Music:
    
    Pictures:
    iPhoto Library
    
    Public:
    Drop Box
    
    Sites:
    images     index.html
    
    personal:
    [localhost:~] dr_unix% 
    

If you want to suppress the directory expansion with ls so that they are in fact the same, there is the '-d' flag:

    [localhost:~] dr_unix% ls -d *
    Adam.txt   Documents  Movies     Pictures   Sites      temp.html  who_list
    Desktop    Library    Music      Public     personal   test_1.txt
    [localhost:~] dr_unix% ls -d
    Adam.txt   Documents  Movies     Pictures   Sites      temp.html  who_list
    Desktop    Library    Music      Public     personal   test_1.txt
    [localhost:~] dr_unix% 
    

If you want a list of all the files starting with 'D', or ending with '.txt', or containing 'st' anywhere, just type:

    [localhost:~] dr_unix% ls -d D*
    Desktop   Documents
    [localhost:~] dr_unix% ls *.txt
    Adam.txt   test_1.txt
    [localhost:~] dr_unix% ls *st*
    test_1.txt who_list
    [localhost:~] dr_unix% ls -d d* *.txt *st*
    Adam.txt   Desktop   Documents test_1.txt who_list
    [localhost:~] dr_unix%
    

Note that metacharacters are expanded into a list and then shoved into the command. Notice that, in the example provided here, there are two directories that start with 'D'. If you pass the argument 'D*' to cd,

    [localhost:~] dr_unix% cd D*
    D*: Ambiguous.
    [localhost:~] dr_unix% ls -d D*
    Desktop   Documents
    [localhost:~] dr_unix% 
    

you get an error message (D*: Ambiguous.). What happens is that, behind the scenes, the shell looks for all files that can be described with 'D*', expands that to 'Desktop Documents', and this is passed to the cd command, which becomes cd Desktop Documents. Since cd takes (at most) one argument, the cd command burps. Neat, huh?

'*' is, by far, the most commonly used filename metacharacter, but the others can be quite handy, when needed. (After all, that's why they exist; they are more common in shell scripts, but can be useful on the command line as well.) The '?' metacharacter is used less often, but when it is needed, it's indispensable. It will substitute for any one character, and '?'s can be strung in series to emulate 'any character, a specific number of times':

    [localhost:~] dr_unix% ls t*
    temp.html  test_1.txt
    [localhost:~] dr_unix% ls te??.*
    temp.html
    [localhost:~] dr_unix% 
    
The '[]' metacharacters are mostly used in shell scripting, and rarely then, but again, they're available in Unix for a reason. The shell will match any character that is between the brackets.
    [localhost:~] dr_unix% ls
    Adam.txt   Documents  Movies     Pictures   Sites      temp.html  who_list
    Desktop    Library    Music      Public     personal   test_1.txt
    [localhost:~] dr_unix% ls te*
    temp.html  test_1.txt
    [localhost:~] dr_unix% ls te[mno]*
    temp.html
    [localhost:~] dr_unix% 
    

If you want to look for a range of characters, you can use the '-' character:

    [localhost:~] dr_unix% ls *.txt
    Adam.txt   test_1.txt
    [localhost:~] dr_unix% ls [a-z]*.txt
    test_1.txt
    [localhost:~] dr_unix% 
    

(Remember, Unix is case-sensitive, so the 'A' character is not the same as the 'a' character.)

In ten years of Unix, I have used the '{}' metacharacters maybe twice, but again, when I needed them, they saved me a lot of work. The shell takes each comma-seperated string in the '{}', expands them into a list, then does whatever else is required.

    [localhost:~] dr_unix% ls
    Adam.txt   Documents  Movies     Pictures   Sites      temp.html  who_list
    Desktop    Library    Music      Public     personal   test_1.txt
    [localhost:~] dr_unix% ls {te}*
    temp.html  test_1.txt
    [localhost:~] dr_unix% ls -d {D,te}*
    Desktop    Documents  temp.html  test_1.txt
    [localhost:~] dr_unix% 
    

The '{}' is rarely used; in fact, I'd forgotten about it until researching this column. But again, when it is needed, it will save you a lot of work.

Two other metacharacters (which aren't strictly filename metacharacters, but are close enough for government work) are '. and '..'. (I know that I've mentioned them before, but they are worth repeating.) These are present in every directory.

    [localhost:~] dr_unix% ls -ad .*
    .                   .DS_Store           .Trash              .cshrc
    ..                  .FBCIndex           .addressbook        .ssh
    .CFUserTextEncoding .FBCLockFolder      .addressbook.lu     .tcsh_history
    [localhost:~] dr_unix% 
    

'.' is a shorthand for many things. In the context of directories, '.' is a shorthand for 'this directory'.

    [localhost:~] dr_unix% ls
    Adam.txt   Library    Pictures   personal   test_1.txt
    Desktop    Movies     Public     sigquotes  what_list
    Documents  Music      Sites      temp.html  who_list
    [localhost:~] dr_unix% ls .
    Adam.txt   Library    Pictures   personal   test_1.txt
    Desktop    Movies     Public     sigquotes  what_list
    Documents  Music      Sites      temp.html  who_list
    [localhost:~] dr_unix% 
    

Every directory has a '.' directory referring to itself. This may not seem too useful now, but it will be quite handy later on. Using '..', on the other hand, is so common that you will wonder how you ever got on without it. It means 'my parent directory'.

    [localhost:~] dr_unix% pwd
    /Users/dr_unix
    [localhost:~] dr_unix% cd ..
    [localhost:/Users] dr_unix% pwd
    /Users
    [localhost:/Users] dr_unix% 
    

Every directory has a '..' referring to its parent directory. (The one exception is the root directory, '/', in which case it refers to itself.)

Now that we have looked at the filename metacharacters, options, and arguments, and have seen how a couple of the basic commands are used in action, we are ready for some meatier topics. We'll start with manipulating files and directories in the next column.

You are encouraged to send Richard your comments, or to post them below.


Most Recent Mac OS X Command Line 101 Columns

Command Line History & Editing Your Commands
November 22nd

Pico: An Easy To Use Command Line Editor
November 1st

Understanding The "grep" Command In Mac OS X
October 4th

Command Line History & Editing Your Commands
September 6th

Mac OS X Command Line 101 Archives

Back to The Mac Observer For More Mac News!


Richard Burton is a longtime Unix programmer and a handsome brute. He spends his spare time yelling at the television during Colts and Pacers games, writing politically incorrect short stories, and trying to shoot the neighbor's cat (not really) nesting in his garage. He can be seen running roughshod over the TMO forums under the alias tbone1.



Today's Mac Headlines

[Podcast]Podcast - Apple Weekly Report #135: Apple Lawsuits, Banned iPhone Ad, Green MacBook Ad

We also offer Today's News On One Page!

Yesterday's News

 

[Podcast]Podcast - Mac Geek Gab #178: Batch Permission Changes, Encrypting Follow-up, Re-Enabling AirPort, and GigE speeds

We also offer Yesterday's News On One Page!

Mac Products Guide
New Arrivals
New and updated products added to the Guide.

Hot Deals
Great prices on hot selling Mac products from your favorite Macintosh resellers.

Special Offers
Promotions and offers direct from Macintosh developers and magazines.

Software
Browse the software section for over 17,000 Macintosh applications and software titles.

Hardware
Over 4,000 peripherals and accessories such as cameras, printers, scanners, keyboards, mice and more.

© All information presented on this site is copyrighted by The Mac Observer except where otherwise noted. No portion of this site may be copied without express written consent. Other sites are invited to link to any aspect of this site provided that all content is presented in its original form and is not placed within another .