Terminal Primer – Part 2 – Navigating the File System

It is vacation time here in the Scripting OS X headquarters and I will be traveling with family for most of August. The Weekly News Summaries are also on vacation, but to compensate for that I will be posting a draft of parts of my next book on macOS Terminal and bash. Let me know how you like them or if you think something important is wrong or missing. You can give feedback in the comments, over Twitter or in the MacAdmins forum (also scriptingosx). Thank you for your interest and feedback!

Working Directory

Back to our earlier example, the pwd command. You entered the command pwd and the shell returned a result:

$ pwd
/Users/armin

Your output will be different. Unless your name is also armin, the path will end with your user name, not mine. Depending on the configuration of your Mac, your path might be entirely different.

pwd is short for ‘print working directory.’ It shows the folder this shell is currently working in, much like a Finder window displays the contents of a certain folder.

On macOS, Terminal will also show the working directory in the window title bar.

Paths

Modern file systems are hierarchical and have many folders and files nested in each other. In a Unix shell you denote a folder or file in another folder with the forward ‘/’ slash character. The complete series of folders to a file or folder is called its ‘path.’

For example, if there is a file hello.txt in your Documents folder in your home directory, its complete path or absolute path is:

/Users/armin/Documents/hello.txt

A path starts at the ‘root’ of the file system, which is shown as simply /. On macOS the root of the file system is the top level of the volume or disk with the active system, i.e. the current startup volume of the Mac.

Note: The file system root / should not be confused with the system user root.

This path tells me (and the shell) that there is a file ‘hello.txt’ in a folder ‘Documents’ in a folder ‘armin’ in a folder ‘Users’ on the root of the file system, the current startup volume.

Note: Finder in macOS and other graphical interfaces use the word ‘folder.’ Unix and other command line shells use the word ‘directory.’ They are the same.

Relative Paths

Addressing files and folders with their full path each and every time would be very tedious. To help with that a shell has a ‘current working directory.’

You can refer to files and folder relative to the shell’s current working directory. When using relative paths, there is no initial /.

hello.txt

refers to the file ‘hello.txt’ in the current working directory.

Documents/hello.txt

refers to the file ‘hello.txt.’ in the folder ‘Documents’ in the current working directory.

Relative paths do not have a leading / and are relative to the current working directory. Full paths start with a / and are based in the file system root. Full paths are also called ‘absolute’ paths.

It is surprisingly easy to lose track of the current working directory. You can ask the shell for the current working directory with the pwd command.

Mac:~ armin$ pwd
/Users/armin

Changing Directories

You can change the current working director with the cd command (change directory):

Mac:~ armin$ cd Documents
Mac:Documents armin$ pwd
/Users/armin/Documents

Use the cd command with a relative path Documents and the shell changes it working directory there. The pwd command prints the full path of the working directory.

You can also navigate to an absolute path:

Mac:Documents armin$ cd /Library
Mac:Library armin$ pwd
/Library
Mac:Library armin$ cd /
Mac:/ armin$ pwd
/

You may have noticed that the prompt displays the name of the current directory. This helps you remember your ‘bearings’ in terminal. Terminal on macOS will also display the current working directory in the window title bar.

You can open a second terminal window by selecting ‘New Window with Settings – Basic’ from the ‘New Window’ menu in the ‘Shell’ menu. It is easier to remember the ⌘N (command-N) keystroke. If you prefer you can also open new shells in a new Tab with ⌘T.

The second window or tab will start a second, new bash shell. This shell is entirely separate of the first bash shell. Different shells will have different working directories. They are very much like different windows showing different folder contents in the Finder.

Home Directory

The prompt in the second terminal window will show:

Mac:~ armin$

According to the prompt current working directory is ~?

The tilde ~ is a special character in bash and other shells. It is a shortcut for the user’s home directory or home folder. On macOS a user’s home directory is created in the /Users directory with the user’s short name as the directory name. So if my short name is ‘armin’ my home directory is /Users/armin.
So the ~ in the prompt says the current working directory is my home folder.

Mac:~ armin$ pwd
/Users/armin

Note: It is important that the shell will actually substitute a ~ with the home directory path before executing the command.

You can use the ~ with cd to quickly change the working directory to your home directory

$ cd ~
$ pwd
/Users/armin

You don’t have to use this, though, since cd without any arguments, will change to your home directory.

$ cd
$ pwd
/Users/armin

You can also start a path with ~:

$ cd ~/Documents
$ pwd 
/Users/armin/Documents

Since ~ is replaced with an absolute path to the home directory, paths that start with ~ are absolute as well.

Moving On Up

You can change the working directory into subdirectories and you can change to absolute paths.

You also often want to move up one level in the folder hierarchy, to the parent folder of the current folder.

Now you could remember your current location (or recall it with pwd) and cd to the absolute path of the parent manually. However, there is an easier way to do this:

$ cd ~/Documents/
$ pwd
/Users/armin/Documents
$ cd ..
$ pwd
/Users/armin

In bash (and most other shells) two periods .. represent the parent directory of the current working directory.

You can even use .. multiple times:

$ cd ~/Library/Preferences/ByHost
$ cd ../..
$ pwd
/Users/armin/Library

../.. designates the parent directory of the parent. ../../.. goes up three levels, etc.

Note: if you cd / and then cd .. nothing happens.

Moving Back

The shell remembers the last working directory, as well, even if you don’t. You can quickly switch back to the previous working directory with cd - (minus):

$ cd ~/Documents
$ cd /Library/Preferences
$ cd -
/Users/armin/Documents
Documents $ cd -
/Library/Preferences

To assist orientation, cd - will print the full path to the directory it is changing to.

Tab Completion

Typing paths is tedious and error prone. Errors in paths can lead to simple errors and frustration, and sometimes typos can have catastrophic results.

When you are typing commands, file names or paths in bash, then you can use the tab key ⇥ to save keystrokes and avoid typos.

For example, you can type:

$ cd ~/Doc⇥
and it will complete to
$ cd ~/Documents/ 

Tab completion will add a forward slash / to the end of a directory’s name so you can continue typing the next directory name. You can hit tab over and over at different parts of the command:

$ cd ~/Li⇥
$ cd ~/Library/
$ cd ~/Library/Appl⇥
$ cd ~/Library/Application\ S<beep>
$ cd ~/Library/Application\ Su⇥
$ cd ~/Library/Application\ Support/

When there are multiple options to complete, bash will complete as far as it is unambiguous and will play an alarm sound. When you then press tab for the second time, it will list all options:

$ cd ~/D⇥<beep>⇥
Desktop/   Documents/ Downloads/

Using tab-completion not only saves keystrokes and time, but also reduces the potential for typos and errors.

You may have noted that tab completion did something strange to the space in the path of the ‘Application Support’ folder. There are many special characters that you have to deal with in the shell. Space is one of them. We will learn how to deal with space and the other special characters in the next section.

Note: commands, arguments and file names in bash are case-sensitive. However, since the macOS filesystems (HFS+ and APFS) are case-insensitive by default, you may want to switch tab-completion to be case-insensitive as well , too.

Listing Directory Contents

The next command is ls, which is short for ‘list’.

$ cd ~
$ ls
Desktop     Downloads   Movies      Pictures
Documents  Library     Music       Public

This command will list the contents of the current working directory. The contents of your home directory may be different.

To use the space efficiently ls prints the files and folders in multiple columns (the number of columns depends on the size of your Terminal window).

This simple list can be very useful to lookup file and directory names. However, you cannot tell the difference between files and directories in this list.

You can tell ls to show an extra character to indicate the kind of an entry:
$ ls -F
Desktop/ Downloads/ Movies/ Pictures/
Documents/ Library/ Music/ Public/

This version of ls output will add a slash ‘/’ to directories and an asterisk ‘*’ to executable files. Normal files (documents) will have no extra character.

In this command the -F is an option for the ls command. Options are a special kind of argument. Options usually start with one or two a hyphen characters - and are followed by a letter. Generally options work like switches to turn certain features of the command on or off.

Since the shell is case-sensitive the options -F and -f are different.

Since ls is a very common command, it has many options. The -G option works similar to the -F option but marks the different kinds with colors:

You can use multiple options at once:

$ ls -G -F
Desktop/   Downloads/ Movies/    Pictures/
Documents/ Library/   Music/     Public/

With most commands you can combine multiple options after a single hyphen: ls -GF is the same as ls -G -F

You can also add an argument to ls:

$ ls ~/Desktop

will list the contents of the Desktop directory without changing the working directory. You can combine options and an argument. When you do that you usually put the options before the argument.

$ ls -GF ~/Desktop

Detailed List

The default output of ls is very terse. You can get more information by adding the -l (lower-case L) option.

$ ls -l
total 0
drwx------+  6 armin  staff   204 Jul 18 17:22 Desktop
drwx------+  3 armin  staff   102 Jun  6 11:24 Documents
drwx------+  3 armin  staff   102 Jun  6 11:24 Downloads
drwx------@ 50 armin  staff  1700 Jul 18 16:02 Library
drwx------+  3 armin  staff   102 Jun  6 11:24 Movies
drwx------+  3 armin  staff   102 Jun  6 11:24 Music
drwx------+  3 armin  staff   102 Jun  6 11:24 Pictures
drwxr-xr-x+  5 armin  staff   170 Jun  6 11:24 Public

This command lists one file or directory per line. The columns are (in order):

  • file type and mode
    • first character shows type: (d directory, l link, – file)
  • number of links
  • file owner
  • file group
  • file size in bytes
  • modification date and time
  • name

There are more options that you can use with the -l option. For example the -h option will show file sizes with B (bytes), K (kilobytes), M (megabytes) etc. instead of raw bytes.
You can also combine -l with -G and/or -F.

Invisible Files

Certain files and directories that are invisible in Finder are visible in the shell. The ~/Library folder has been hidden in the Finder since Mac OS X 10.7 Lion, but is easily visible with ls. By convention however, ls does not usually list files and directories that start with a dot or period .. You can make ls show these files with the -a option. Your home directory will already have a few ‘dot-files’:

$ ls -al ~
total 16
drwxr-xr-x+ 15 armin  staff   510 Jul 18 15:30 .
drwxr-xr-x   7 root   admin   238 Jul 19 08:35 ..
drwx------   4 armin  staff   136 Jul 19 14:55 .Trash
-rw-------   1 armin  staff   402 Jul 19 08:39 .bash_history
drwx------   3 armin  staff   102 Jul 13 09:16 .ssh
drwx------+  8 armin  staff   272 Jul 19 14:57 Desktop
drwx------+  3 armin  staff   102 Jun  6 11:24 Documents
drwx------+  3 armin  staff   102 Jun  6 11:24 Downloads
drwx------@ 50 armin  staff  1700 Jul 18 16:02 Library
drwx------+  3 armin  staff   102 Jun  6 11:24 Movies
drwx------+  3 armin  staff   102 Jun  6 11:24 Music
drwx------+  3 armin  staff   102 Jun  6 11:24 Pictures
drwxr-xr-x+  5 armin  staff   170 Jun  6 11:24 Public

In UNIX files and directories that start with a period are commonly used to store configuration data.
The first two entries in this list are . and ... We already know that .. represents the parent directory (in this case of the directory listed). The single period . is another convention that represents the current directory or (in this case the directory listed). This can be useful to see the file mode and owner of these directories right here.

Note: Finder also follows this convention and hides ‘dotfiles’ by default. You can learn more about hidden files and folders in this article.

Summary

So far we have encountered three commands to navigate the file system: pwd, cd, and ls

pwd prints the current working directory.

$ pwd
/Users/armin/Documents

cd changes the working directory to another.

You can use absolute paths (that begin with /):

$ cd /Library/Application\ Support
$ cd /

or paths relative to the current working directory (no leading /):

$ cd Documents

Two periods .. represent the parent directory:

$ cd ..

changes the working directory to the parent directory.

The tilde ~ represents your home directory. You can use it alone or to start a path to folders and files in your home directory.

$ cd ~
$ cd ~/Documents

The ls command lists the contents of the current working directory:

$ ls
Desktop        Downloads   Movies      Pictures
Documents  Library     Music       Public

The ls command has many options. The most commonly used are probably -l to show a detailed list of the files and folders and -a to also show the files and directories starting with a period, which are usually hidden.

Leave a Reply

Your email address will not be published. Required fields are marked *