Look Around – Take Control of the Mac Command Line with Terminal, 3rd Edition

Look Around

In this chapter, I help you find your way around your Mac from the command line and, at the same time, teach you some of the most common navigational commands and conventions.

For right now, you’re going to look, but not touch—that is, nothing you do here can change any files or cause any damage, as long as you follow my instructions.

Discover Where You Are

Ready to start learning some commands? Here we go. Open a Terminal window and enter this:

pwd

The pwd command stands for “print working directory,” and it gives you the complete path to the directory you’re currently using. If you haven’t done anything else since opening a Terminal window, that’s your home directory, so you’ll see something like this:

/Users/jk

That’s not exciting, but it’s extremely important. As you navigate through the directory structure, it’s easy to get lost, and ordinarily your prompt only tells you the name of your current directory, not where it’s located on your disk. When you’re in a deeply embedded directory, being able to tell exactly where you are can be a huge help.

See What’s Here

If you were in the Finder, you’d know exactly what’s in the current folder just by looking. Not so on the command line; you must ask explicitly. To get a list, you use the “list” command:

ls

What you get by default is a list along the lines of the following:

Desktop      Downloads     Movies       Pictures
Documents    Library       Music        Public

Items are listed alphabetically, top to bottom and then left to right. But as you can see, this doesn’t tell you whether these items are files or directories, how large they are, or anything else about them. So most people prefer the more-helpful long format by adding the -l flag:

ls -l

This produces a result something like:

drwx------@  18 jk    staff    612 Feb 12 09:42 Desktop
drwx------@ 108 jk    staff   3672 Feb  9 14:35 Documents
drwx------@  15 jk    staff    510 Feb 12 11:17 Downloads
drwx------+  94 jk    staff   3196 Feb 11 22:40 Library
drwx------@  13 jk    staff    442 Dec 30 15:34 Movies
drwx------@  15 jk    staff    510 Aug 27 15:02 Music
drwx------+  14 jk    staff    476 Jan 26 19:40 Pictures
drwxr-xr-x+   7 jk    staff    238 Jan 22 23:13 Public

Reading from right to left, notice that each line ends with the item’s name. To the left of the name is a date and time showing when that item was most recently modified. To the left of the date is another number showing the item’s size in bytes. See the sidebar on the next page, Making Output (More) Human-Readable, to find out how to turn that number into a nicer format. (In the case of a directory, the number shown by ls -l doesn’t tell you the total size of the directory’s contents, only the size of the information stored about the directory. The “disk usage” command can get a directory’s size, enter du -sh directory-name.)

Later in this book, in Understand Permission Basics, I go into more detail about all those characters that occupy the first half of each line, such as drwxr-xr-x +   7 jk    staff; those characters describe the item’s permissions, owner, and group. For the moment, just notice the very first letter—it’s d in every item of this list. The d stands for “directory,” meaning these are all directories. If the item were a file, the d would be replaced with a hyphen (-), for example: -rwxr-xr-x.

Finally, look at one other number, between the permissions and owner (in drwx------   14 jk the number is 14). That’s the number of links to the item, and although links are too advanced to explain in detail here, the number serves one practical purpose: it gives you an approximation of the number of items in a directory. In fact, it is always at least two higher than the number of visible files or directories in the directory (for complicated reasons). For now, just know that the number can tell you, at a glance, if a directory has only a few items or many.

However, as I hinted in The Startup Volume is Read-Only, starting in Catalina, the ls command doesn’t always tell the entire story. For example, if you enter ls /Applications you’ll see only the third-party applications (which are really stored in Macintosh HD - Data/Applications). What if you want to see the apps built into macOS—the ones that are stored in Macintosh HD/Applications? In that case, you have to enter ls /System/Applications. (The same goes for /Library and other top-level directories.) You can’t use the ls command to show you the merged contents of these folders as the Finder does.

I don’t want to belabor the ls command, but it will without question be one of the top two or three things you type on the command line—you’ll use it constantly. So it pays to start getting ls (along with a flag or two) into your muscle memory. For a way to display even more information with ls, see the recipe List More Directory Information.

Repeat a Command

If you’ve just entered a two-character command, it’s no big deal to enter it again. But sometimes commands are quite complex, wrapping over several lines, and retyping all that is a pain. So I want to tell you about two ways of repeating commands you’ve previously entered.

Arrow Keys

First, you can use the ↑ and ↓ keys to move backward and forward through the list of commands you’ve recently typed. For example, if the last command you typed was ls -lh, simply pressing ↑ once puts that on the command line. (Then, to execute it, you would press Return or Enter.) Keep pressing ↑, and you’ll step backward through even more commands. You can even scroll through commands you entered in previous sessions. The ↓ key works the same way—it progresses forward in time from your current location in the list of previous commands.

The !! Command

Another handy way of repeating a command is to enter !! (that’s right: just two exclamation points). This repeats your previous command. Try it now. Enter, say, pwd, and get the path of your current directory. Then enter !! and you’ll get the same output.

Again, this isn’t terribly interesting when you’re talking about short commands, but it can save time and effort with long commands.

Cancel a Command

What if you type some stuff on the command line and realize you don’t want to enter the command? Well, you could backspace over it, but that may take a while if there’s a lot of text on the line.

An easier way to back out of a command without executing it is to press either Control-C or ⌘-. (period). The shell creates a new, blank command line, leaving your partially typed line visible but unused. (Your command history won’t include canceled commands.)

Move into Another Directory

This has been a lovely visit in your home directory, but now it’s time to explore. To change directories, you use the cd command. As you saw a moment ago, one of the directories inside your home directory is called Library. Let’s move there now, like so:

cd Library

When you put a directory name after the cd command, it assumes you want to move into that directory in your current location. If there doesn’t happen to be a directory called Library in your current directory, you see an error message like this (preceded by -bash if you’re using the bash shell):

cd: Library: No such file or directory

As a reminder, the command-line environment doesn’t list the contents of a directory unless you ask it to (using ls), so using cd doesn’t automatically show what’s in your new location. You know the command succeeded if you don’t see an error message, and by default your prompt includes the name of your current directory.

Move Up or Down

Now that you’re in the Library directory that’s in your home directory (~/Library), you can use ls to look around; you’ll see that one of the directories inside the current one is Preferences. To move down a level into preferences, you’d enter cd Preferences. And so on.

To go up a level, you use the .. convention, which means “the directory that encloses this one.” For example, if you’re in /Users/jk/Library/Preferences, the directory that encloses it is /Users/jk/Library, so in this particular location two periods (..) means /Users/jk/Library.

To get there, you enter:

cd ..

That translates as “change directories to the one that encloses this one.” You can keep going up and down with cd .. and cd directory (fill in the name of any directory) as much as you like.

Move More Than One Level

Nothing says you have to move up or down just one level at a time. If you’re currently in /Users/jk and you know that there’s a Library directory inside it, and inside that there’s a Preferences directory, you can jump directly to Preferences like so:

cd Library/Preferences

The slash (/) simply denotes that the term to its right is a directory inside the term on its left: Preferences is a directory inside Library. You can add on as many of these as you need:

cd Library/Logs/Adobe/Installers

This also works in the other direction. If you’re in /Users/jk/Library/Preferences, you can enter cd .. to move into Library. Or, enter cd ../.. to move directly into jk, or cd ../../.. to move into Users.

Move to an Exact Location

So far, we’ve been moving using relative locations—a directory inside the current one, or a directory that encloses the current one. But if you know exactly where you’re going, you can jump directly to any location on your Mac. Just specify the full path, beginning with a slash (/), which represents the root level of your disk. For example, enter this:

cd /private/var/log

That takes you directly to /private/var/log (a rather boring directory full of—you guessed it—log files, and one that’s normally invisible in the Finder) without having to navigate all the way up to the root level of your disk and then back down.

Speaking of the root level: If you want to go to the very top of your disk hierarchy, just enter this:

cd /

Move Between Two Directories

Another handy shortcut, which lets you go back to the last directory you were in, is this:

cd -

For example, suppose I start in my home directory and then I enter cd /Users/Shared. I do some things in that directory, and I next enter cd ~/Library/Preferences to do other work there. If I then enter cd - I jump back to /Users/Shared (the last directory I was in), without having to type or even remember its path.

Jump Home

Once you’ve changed directories a few times, you may want to get back to your home directory. Of course, you could keep navigating up or down, one directory at a time, until you got there, or you could enter the complete path to your home directory (cd /Users/jk, for example). But macOS has another shortcut (along the lines of ..) that means “the current user’s home directory”: the tilde (~).

So one way to jump home, from any location on your disk, is to enter:

cd ~

But in fact, it can be even easier. If you enter cd alone, with nothing after it, the command assumes you want to go home, so cd by itself does the same thing as cd ~.

Just as you can enter the full path after cd to jump to any spot on your disk, you can substitute ~ whenever you’d otherwise use the full path to your home directory. So, even if you’re in /private/var/tmp, you can go directly to the Library directory inside your home directory with:

cd ~/Library

Understand How Paths Work

You’ve already seen both relative paths (such as Library/Preferences, which means the Preferences directory inside the Library directory inside my current directory) and absolute paths, which begin with a slash (such as /Library/Preferences, which means the Preferences directory inside the Library directory at the top level of your disk). But there are a few other things you should understand about paths.

Spaces in Paths

macOS lets you put almost any character in a file or folder name, including spaces. But space characters can get you in trouble in the command-line environment, because normally a space separates commands, flags, and arguments.

Suppose you were to enter this:

cd My Folder

Even if there were a folder named My Folder in the current directory, the command would produce an error message, because the cd command would assume that both My and Folder were intended to be separate arguments.

You can deal with spaces in either of two ways:

  • Quotation marks: One way is to put the entire path in quotation marks. For example, entering cd "My Folder" would work fine.

  • Escape the space: The other way is to put a backslash (\) before the space—this escapes the space character, making the shell treat it literally rather than as a separator between arguments. So this would also work: cd My\ Folder.

Terminal automatically escapes the name of a file or folder when you drag it in from the Finder. See Get the Path of a File or Folder, later.

Wildcards

You can use wildcards when working on the command line; these can save you a lot of typing and make certain operations considerably easier. The two wildcards you’re most likely to use are these:

  • * (asterisk): This means “zero or more characters.” For example, if you want to switch to a directory called Applications, you could enter cd App* and, as long as there was no other directory there that started with those three letters, you’d go directly to the Applications directory. (I talk about another way of doing something similar ahead a few pages in Use Tab Completion.)

    You can use this wildcard with almost any command. For instance, if you’re in your home directory, you could type ls D* to list all and only the items that begin with “D” (Desktop, Documents, Downloads).

  • ? (question mark): This means “any single character.” That means ?at could match bat, cat, fat, rat, sat, and so on. If you have many files with similar names—say, sequentially numbered photos—you could limit the ones listed with something like ls 01??.jpeg.

Case Sensitivity

Here’s a trick question: is the macOS command line case-sensitive? The answer is yes—and no! Suppose you’re in ~. There’s a directory in there called Pictures, and you could move into it in any of these ways (among others):

cd Pictures

cd pictures

cd Pic*

cd pic*

That certainly seems to suggest that the command line is not case-sensitive, because using either p or P has the same effect. But it’s possible to format a Mac volume to use a case-sensitive version of the APFS or Mac OS Extended (HFS+) file systems. If you do that—or if you connect to an external disk or network volume that uses a case-sensitive file system—then you could see both a pictures directory and a Pictures directory in the same place, in which case using the wrong case with the cd command will take you to the wrong directory.

You won’t see any visual cue to let you know whether a particular volume uses a case-sensitive format. So the safest assumption is to always use the correct case: that always works.

Understand the macOS Directory Structure

You surely know from day-to-day use that your Mac has a bunch of standard folders at the top level of your startup disk—Applications, Library, System, and Users, at minimum. You may have also noticed that each user’s home folder has its own Library folder (not to mention a Desktop folder, a Documents folder, and several others). In addition to these and the numerous other folders you can see in the Finder, macOS has a long list of directories that are normally invisible (because most users never need to interact with them directly), but you can see them from the command line.

I could explain what every single (visible) folder and (hidden) directory is for, and how to make sense of the elaborate hierarchy in which macOS stores all its files. But that would take many pages and, honestly, it would be mighty boring. So I’m going to let you in on a little secret: you don’t have to know.

I mean it: you don’t have to know why one program is stored in /bin while others are in /usr/bin, /usr/local/bin, or any of numerous other places. You don’t need to know why you have a /dev directory or what goes in /private/var. Seriously. Knowing all those things might be useful if you’re a programmer or a system administrator, but it’s absolutely irrelevant for ordinary folks who want to do the kinds of things discussed in this book. True, I may direct you to use a program in /usr/sbin or modify a file in /private/etc (or whatever), but as long as you can follow the instructions to do these things, you truly don’t have to know all the details about these directories.

So, instead, I want to provide a very short list of the key things you should understand about the macOS directory structure:

  • The invisible world of Unix: If you enter ls -l / (go ahead and do that), you get a list of all the files and directories at the root level of your disk. You’ll see familiar names such as Applications and Users, and some less-familiar ones, such as bin and usr. Here at the root level, directories that begin with a lowercase letter and aren’t shown in the Finder (such as bin, cores, dev, private, sbin, usr, and var), along with their contents, make up Darwin, the Unix core of macOS. Similar directories appear in other Unix and Unix-like operating systems.

  • Recursion, repetition, and recursion: If you were to work your way from the root of your disk down through all its directories and subdirectories, you’d notice a lot of names that appear over and over again. For example, there’s a top-level /Library directory, another inside /System, and yet another inside each user’s home directory (~/Library). Similarly, there are top-level /bin and /sbin directories, but also /usr/bin and /usr/sbin. The reasons for all these copies of similar-looking directories are sometimes practical, sometimes purely historical. But everything has its place.

    You don’t have to grasp all the logic behind what goes where, but you do have to be sure you’re in the right place when you work on the command line. For instance, if an example in this book tells you to do something in ~/Library, be absolutely sure that’s where you are, as opposed to, say, /Library. The smallest characters—in particular, the period (.), tilde (~), slash (/), backslash (\), and space ( ), have the utmost significance on the command line, so always pay strict attention to them!

  • The bandbox rule: My grandfather had a curious and oft-repeated expression: “Don’t monkey with the bandbox.” He (and, subsequently, my mother) used this to mean, approximately, “Don’t mess with something if you could break it and not be able to put it back together.” (As a child, I had quite a propensity for disassembling things and then getting stuck!)

    On the command line, this means don’t go deleting, moving, or changing files if you don’t know what they are or what the consequences could be. Something that seems insignificant or useless to you could be crucial to the functioning of your Mac. (As a corollary, it should go without saying that you back up your Mac thoroughly and regularly—see my book Take Control of Backing Up Your Mac if you want detailed advice on the subject.)

Use Tab Completion

Because everything you do on the command line involves typing, it can get kind of tedious spelling out file and directory names over and over again—especially since even the slightest typo can make a command fail! So the zsh and bash shells include a number of handy features to reduce the amount of typing you have to do. Earlier I explained how to use the arrow keys and the !! command to repeat previous commands (Repeat a Command). Now I want to tell you about a different keystroke-saving technique: tab completion.

Here’s the basic idea. You start typing a file or directory name, and then you press the Tab key. If only one item in the current directory starts with the letter(s) you typed, the shell fills in the rest of that item’s name. If there’s more than one match, you’ll hear a beep; press Tab again to see a list of all the matches.

For example, try this:

cd

Now that you’re in your home directory, type cd De (without pressing Return) and press Tab. Your command line should look like this:

cd Desktop/

If you do want to change to your desktop directory, you can simply press Return. Or, you can type more on the line if need be. For now, let’s stay where we are—press Control-C to cancel the command.

Next, try typing cd D (again, without pressing Return) and press Tab. You should hear a beep—signifying that there was more than one match—but nothing else should happen. Press Tab again. Now you’ll see something like this:

Desktop/   Documents/   Downloads/

And, on the previous line (in zsh) or next line (in bash), your command-in-progress appears again exactly as you left it off:

cd D

In this way, tab completion lets you know what your options are; you can type more letters (say, oc) and press Tab again to have it fill in Documents/ for you. In zsh, you can keep pressing Tab to cycle through matching options, and press Return when the one you want appears.

Tab completion isn’t limited to just the current directory. For example, enter cd ~/Lib and press Tab. The shell fills in the following:

cd ~/Library/

Now type Fav and press Tab. You should see Favorites filled in:

cd ~/Library/Favorites/

You can keep going as many levels deep as you need to.

Find a File

In the command-line environment, as in the Finder, you may not know where to find a particular file or directory. Two commands can supply that information readily: find and locate. Each has its pros and cons.

Find

To use the find command, you give it a name (or partial name) to look for and tell it where to start looking; the command then traverses every directory in the area you specify, looking at every single file until it finds a match. That makes it slow but thorough.

For example, suppose I want to find all the files anywhere in my home directory with names that contain the string keychain. I can do this:

find ~ -name "*keychain*"

After the command find, the ~ tells the command to begin looking in my home directory (and work its way through all its subdirectories). The -name flag says to look for patterns in the last item of a path (which may include the names of directories as well as files). I put the search string inside quotation marks, with an asterisk (*) wildcard at the beginning and end to signify that there may be other letters before or after keychain.

Even a simple search such as this one can take several minutes, because it must look at every single file, starting at the path I specified. To make it go quicker, I could specify a narrower search range. For example, to have it look only in my ~/Library directory, I’d enter:

find ~/Library -name "*keychain*"

Let me offer a few other tips for using find:

  • To search in the current directory (and all subdirectories), use a period (.) as the location: find . -name "*keychain*".

  • To search your entire disk, use a slash (/) as the location:
    find / -name "*keychain*".

  • Normally, find is case-sensitive, so a search for "*keychain*" would not match a file named Keychain. To make a search case-insensitive, replace -name with -iname, as in find ~ -iname "*user data*".

  • During a search, if find encounters any directories you don’t have permission to search, it displays the path of the directory with the message “Permission denied.” To search these paths, use sudo before find, as described in Perform Actions as the Root User.

Locate

The other way to find files by name is to use the locate command. Unlike find, locate doesn’t traverse every file to find what you’re looking for. Instead, it relies on a database (index) of file and path names. The benefit of using the index is that locate is lightning fast. The downside is, the database is normally updated only once a week, so locate may be unable to find files you’ve added or renamed recently.

To use locate, just type that command followed by any portion of the filename you want to look for (no wildcards required). For example:

locate keychain

Like find, locate performs case-sensitive searches by default. To make a search case-insensitive, add the -i flag:

locate -i keychain

If you enter locate and get an error stating that no database exists—or if it exists but is outdated—you can create or update it by entering this:

/usr/libexec/locate.updatedb

The command may take some time to complete, because it does have to look at every file on your disk—or nearly so.

I’ve skipped over one important detail: by default, locate indexes (and finds) only files you own (mostly the contents of your home directory). However, if you run the database updating script using sudo (see Perform Actions as the Root User), it indexes every file on your disk, and locate can therefore find every file.

The benefit of this is being able to find more files with locate, but if you attempt to do this, a security warning appears informing you that once you’ve indexed all your files, any user of your Mac can discover the name and location (though not the contents) of any file on your disk. Moreover, the next time the locate database updates on its weekly schedule, your system-wide index of files will be replaced with a version that contains only those you have permission to read.

View a Text File

You may not read a lot of plain text files in the Finder, but the need to do so comes up more frequently in the command-line environment—reading documentation, examining programs’ configurations, viewing shell scripts, inspecting logs, and numerous other situations. You can use many tools to read a file, of which I cover just a few here. (If you want to modify a text file, see Edit a Text File, later.)

You can use these commands with any text file on your Mac, but in these examples I use a file every Mac user should have: a dull Read Me file about OpenLDAP schema, located at /etc/openldap/schema/README.

More or Less

An early Unix program for reading text files was called more. It was pretty primitive and wouldn’t let you move backward to see earlier text. So a new program came along that was supposed to be the opposite of more: less. In macOS, both names still exist, but they point to the same program; whether you enter more or less, you’re actually running less. (There are some subtle differences depending on which command you use, but they’re not worth mentioning.)

You can use less to read a text file like this:

less /etc/openldap/schema/README

You see the top portion of the file initially. You can scroll down a line at a time using the ↓ key (and back up using the ↑ key), scroll ahead a screen at a time by pressing the Space bar, or backward a screen at a time by pressing the B key (all by itself). To quit less, press the Q key (all by itself).

Cat

The Unix cat command (short for “concatenate”) combines files, but you can also use it to display a text file on your screen. Unlike less, it doesn’t give you a paged view; it simply pours the entire contents of the file, regardless of length, onto your screen. You can then scroll the Terminal window up and down, as necessary, to view the contents. To use cat, follow this pattern:

cat /etc/openldap/schema/README

Tail

If you open a long text file with less, it can take quite a bit of tapping on the Space bar to reach the end, which is awkward if the information you want happens to be at the end—as is the case with most logs. And if you use cat, it can clutter your Terminal window with lots of information you don’t need. To jump to the end of a text file, use a different program: tail, which displays the tail end of a file.

If you enter tail followed by the filename, it displays the last 10 lines of the file:

tail /etc/openldap/schema/README

The tail command has flags that enable you to control how much of the file is shown and in what way, but for the sake of brevity I want to mention just one: -n (number of lines). Type tail followed by the -n flag, a space, and a number to set the output to that number of lines from the end of the file:

tail -n 50 /etc/openldap/schema/README

Get Help

Almost every program and command you use on the command line has documentation that explains its syntax and options, and in many cases includes examples of how to use the command. This documentation isn’t always clear or helpful, but it’s worth consulting when you have a question. You can get at these manual pages in several ways.

In a Terminal Window

When you’re on the command line, the quickest way to get information about a command is to use the man (“manual”) command. Simply enter man followed by the command you want to learn about. For example:

man ls

man cp

man locate

The results appear in a viewer that works like less.

To put a slightly prettier (and scrollable) display of man pages on the screen side by side with your working Terminal window, you can also click Terminal’s Help menu, type the name of a command in the Search field, select the item you want, and press Return. If the command is already visible anywhere in the Terminal window, you can right-click (or Control-click) it and choose “Open man Page” from the contextual menu to view it in a separate window. Or, if your cursor happens to be immediately to the right of the term you want to see the man page for, simply press ⌘-Control-?.

Clear the Screen

As you work in Terminal, your window may fill up with commands and their output. The command line itself is always the last line, but the rest of the window can become cluttered with the residue of earlier commands. Here are some ideas for decluttering the window:

  • If you find all that text distracting and want to clear the window (so it looks much like it did when you started the session), enter clear or press Control-L. Terminal moves your command line up to the top of the window with empty space below it (you can still scroll up to see what was on the screen earlier).

  • To hide text that scrolled by in the Terminal window (perhaps to keep someone else from seeing what you did), press ⌘-K.

  • To clear the screen and prevent someone from scrolling back in Terminal to see your earlier activity (handy when you log out!), press ⌘-Option-K.

End a Shell Session

When you’re finished working on the command line for a while, you could simply close the Terminal window, or even quit Terminal, but you shouldn’t. That would be a bit like turning off your Mac by flipping the switch on the power strip instead of choosing Apple  > Shut Down. The proper way to end a shell session in Terminal is to enter exit, which gracefully stops any programs you are running in the shell, and then quits the shell program itself. (Starting in El Capitan, the exit command also lists cleanup activities it performs, such as saving your latest session history and deleting older sessions.)

By default, your Terminal window remains open after you’ve done this. If you want it to close when you exit, choose Terminal > Preferences > Profiles > Current Profile Name > Shell. (Note: This setting was on the Settings pane in much older versions of macOS.) From the “When the shell exits” pop-up menu, choose “Close the window.”