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

Columns & Editorials
Mac Links

Mac OS X Command Line 101
by Richard Burton

Command Line History & Editing Your Commands
Part XVII of this series...
November 22nd, 2002

Shome mishtake, shurely?
catchphrase of Private Eye magazine

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 the Hardcore X! forum.

If you've been following this column, not only are you a person of impeccable taste, you're also likely to have typed a mistake on the command line. That's nothing to be ashamed of, we're only human. (Well, you are.) You've probably miss-typed a command and been faced with retyping the whole command again. You might be able to do a copy-and-paste, if the previous command is still on the screen. However, that is not always possible. And if you'll recall, Unix is more than a decade older than the first available GUI (the one on the Apple Lisa); with no mouse, doing a copy-and-paste is not so intuitive. What's needed is a way to move back and forth through a list of previous commands.

You will not be surprised to read that this is possible. And if you know Unix, you will not be surprised to read that there is more than one way to do this.

tcsh provides a very simple mechanism to do this using the arrow keys. It's so simple, in fact, that even a rocket scientist can grasp it. (And I oughta know ...)


Open a terminal window, and type in a few commands: ls, pwd, who, whatever floats your boat. You can now move up and down the list of commands you just typed using the up and down arrow keys. You can also, shock of shocks, move the cursor back and forth across a command with the left and right arrows. It's very similar to moving around pico, the simple editor I discussed in the previous column. It is not pico, though; the pico commands (the CONTROL- characters) don't do the same thing. Sometimes they do nothing, sometimes they cause some goofy behavior, so until you are ready for more than the arrow keys, it's best to avoid them. For the morbidly curious, you can find out what they are by typing bindkey. Make sure you pipe it through the more command, it takes several screens to list them all. You might also want to keep a cool, damp cloth for your forehead within easy reach.

Auto completion is a life saver

One other feature is command completion, which is related to command line editing. Sorta. In your terminal window, go to your home directory:

    [localhost:~] dr_unix% cd
    [localhost:~] dr_unix% 
Now let's look at the directory's list of files, using the -F flag of ls so that directories are denoted by a trailing '/':
    [localhost:~] dr_unix% ls -F
    Adam.txt     Library/     Public/      personal/    testfile
    Desktop/     Music/       Sites/       temp.html    who_list
    Documents/   Pictures/    login        test_1.txt
    [localhost:~] dr_unix% 
Better, use our new tool fgrep to filter out those files which are not directories:
    [localhost:~] dr_unix% ls -F | fgrep '/'
    [localhost:~] dr_unix% 
Say you want to change your default directory to Library. If you are lazy and/or a bad typist, and who isn't, you don't have to type the whole command:
    [localhost:~] dr_unix% cd Library
    [localhost:~/Library] dr_unix% pwd
    [localhost:~/Library] dr_unix% 
Instead, you can simply type (without hitting RETURN):
    [localhost:~] dr_unix% cd Lib
If you now hit TAB, you get:
    [localhost:~] dr_unix% cd Library/
Since there is only one file in the directory that starts "Lib", tcsh will 'complete' the command when you hit the TAB.
    [localhost:~] dr_unix% cd Library/
    [localhost:~/Library] dr_unix% pwd
    [localhost:~/Library] dr_unix% 
Neat, huh?

Get it on, bang a gong...

Now, most of us aren't complete geeks (and some who are won't admit it), so this will take a lot of us a long way. However, there are more powerful forms of command line editing available. Go to your terminal window, and type the ls command:

    [localhost:~] dr_unix% ls
    Adam.txt   Documents  Music      Public     login      temp.html  testfile
    Desktop    Library    Pictures   Sites      personal   test_1.txt who_list
    [localhost:~] dr_unix% 
Now, type !! and hit return:
    [localhost:~] dr_unix% ls
    Adam.txt   Documents  Music      Public     login      temp.html  testfile
    Desktop    Library    Pictures   Sites      personal   test_1.txt who_list
    [localhost:~] dr_unix% !!
    Adam.txt   Documents  Music      Public     login      temp.html  testfile
    Desktop    Library    Pictures   Sites      personal   test_1.txt who_list
    [localhost:~] dr_unix% 
The '!!' command will run the previous command. Notice how, after you hit RETURN, it showed what the command was before it executed it? If you keep typing '!!' over and over again, you can run the ls command from here to Goshen. In fact, tcsh is clever enough that you can add to the previous command:
    [localhost:~] dr_unix% ls
    Adam.txt   Documents  Music      Public     login      temp.html  testfile
    Desktop    Library    Pictures   Sites      personal   test_1.txt who_list
    [localhost:~] dr_unix% !! | grep t
    ls | grep t
    [localhost:~] dr_unix% 

What's behind all this is tcsh's built-in history commands. Each terminal keeps track of a list of the previously run commands, storing up to the number denoted by the "history" variable:

    [localhost:~] dr_unix% echo $history
    [localhost:~] dr_unix% 
Of course, history being just a variable, you can set it to whatever you want, viz:
    [localhost:~] dr_unix% set history=20
    [localhost:~] dr_unix% echo $history
    [localhost:~] dr_unix% 
If you want to see the list of commands in your history, just type history:
    [localhost:~] dr_unix% history
         8  19:39   cd Library
         9  19:39   pwd
        10  19:49   cd ..
        11  19:59   cd Library/
        12  19:59   pwd
        13  20:01   cd
        14  20:01   echo $history
        15  20:01   ls -a
        16  20:01   more login
        17  20:01   w
        18  20:02   ps
        19  20:03   clear
        20  20:03   ls
        21  20:04   ls
        22  20:12   ls
        23  20:12   ls -a
        24  20:19   echo $history
        25  20:20   set history=20
        26  20:20   echo $history
        27  20:23   history
    [localhost:~] dr_unix% 
Notice that this give you a list of commands, each with an event number and a timestamp. You can also print just the last n commands by giving history an argument:
    [localhost:~] dr_unix% history 5
        24  20:19   echo $history
        25  20:20   set history=20
        26  20:20   echo $history
        27  20:23   history
        28  20:26   history 5
    [localhost:~] dr_unix%
!! is a special/default case. If you want to rerun a specific command, you simply type !n, where n is the event number (the sequential number that is at the beginning of each line):
    [localhost:~] dr_unix% !25
    set history=20
    [localhost:~] dr_unix%
If you want to repeat the previous command which started with a string, just type a ! followed by the string:
    [localhost:~] dr_unix% !history history 5 27 20:23 history 28 20:26 history 5 29 20:32 set history=20 30 20:35 more login 31 20:35 history 5 [localhost:~] dr_unix%
(And yes, I did sneak another command in there on you.) This is useful, but not always what you want. Often, you will be using several commands in succession on a particular file, and the name of which will not be the first part of the command. Let's say your history file looks something like:
        54  12:45   cd Documents/novels/
        55  12:45   ls
        56  12:46   vi big_fish_little_blonde.txt
        57  12:49   nethack
        58  14:32   ls -l big_fish_little_blonde.txt
        59  14:32   wc -l big_fish_little_blonde.txt
        60  14:32   vi big_fish_little_blonde.txt
        61  14:33   nethack
        62  16:09   pwd
(If that looks silly, that's because it's based on two inside jokes, and darned obscure ones, known to some people in our forums.) If you want to repeat the last command on the file, put ?s around the string:
    [localhost:~] dr_unix% !?big_fish?
That will take you back into vi, editing the file so named

Multiple histories

If you open several terminals at once and fool around with each one's command history, you will notice that each terminal's command history is kept separate from the others. However, if you want to open another terminal later and have it know the history you now have, this can be done. (Didn't you just know it?)

If you set the savehist shell variable (by simply typing set savehist), the shell will save its history list to the file ~/.history when you log out. The next time you log in, this file is read and the list is placed into the new shell's history list. If savehist is not given an argument, the entire list is saved to ~/.history; if you give it a value (which should be less than the value of $history), it will save that many of the most recent commands.

More useless command stuff

There are more things in manipulating command history, but I have found them useful in rare cases, if ever. Given all that there is and how rarely you use it, the remaining commands are ignorable. But if you just half to know them all, a good book on csh and/or tcsh should list those commands.

Editing Your Commands

As I've mentioned before, Unix has a couple of text editors that are powerful. What's more, they inspire great loyalty or derision, depending on your prejudices. Now, given the nature of Unix, or rather Unix developers, you would expect that someone could choose to use vi or emacs commands to edit your commands, search through the history lists, etc. What else would you expect from such charming rogues (vi) and rakish chaps (emacs), plus the occasional handsome brute?

Well, you can, and it is done with the bindkey command. bindkey will let you set your editing commands to either emacs (bindkey -e) or to vi (bindkey -v). For now, we will look at the vi version, for two reasons: vi has already been covered in this series, and the emacs version doesn't require any explanation, once you know emacs.

As I'm sure you'll recall, vi has a command mode and an input mode. To enter the input mode, you need to enter one of several commands (i, a, R, etc.). To return to command mode requires hitting the ESCAPE key. Now, if you think about it, normally you just want to start typing commands and not have to worry about editing the commands. It would be pretty silly to have to start each command by typing an 'i' to enter input mode. Therefore, when you set your key binding to vi, you are placed into input mode automatically after each command. To enter command mode, you must hit the ESCAPE key.

Let's try this, shall we? Open a new terminal session, and set your key bindings to vi mode.

    [localhost:~] dr_unix% bindkey -v
    [localhost:~] dr_unix%
(Those of you who know emacs are welcome to set your key bindings with a -e.)

Now type a few familiar commands:

    [localhost:~] dr_unix% pwd
    [localhost:~] dr_unix% w
     3:50PM  up  1:37, 3 users, load averages: 0.60, 0.43, 0.26
    USER    TTY FROM              LOGIN@  IDLE WHAT
    dr_unix  co -                 2:15PM  1:37 -
    dr_unix  p1 -                 2:20PM     0 -
    dr_unix  p2 -                 3:39PM     0 -
    [localhost:~] dr_unix% date
    Sat Oct 26 15:50:09 EST 2002
    [localhost:~] dr_unix% 
Now hit ESCAPE to enter command mode. You can move up and down your history list using vi's "j" and "k" commands. You can also move within a command using the movement commands like "w", "E", and so on. This includes the "/" command to search for a command which matches a regular expression. And you can use any vi command to edit that command. As a plus, tcsh lets you use the arrow keys at the same time.

Congratulations, you are now well on your way to being a Unix shell power user. Next, we'll look at handling multiple processes.

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.

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

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 .