17.1. Unix Command Line and the Unix File System

Unix systems provide a command line interface for users to interact with the system. When a user logs into a Unix system, they interact with a Unix shell program that runs in a terminal window. The shell reads in commands entered by the user and performs the requested action. Example shell programs are bash and zsh. The shell displays a shell prompt (e.g., $) and the user types in a command that the shell program executes. Readers (especially those who know Python) may be familiar with a read-eval-print loop (or REPL), which is a shell-like environment that is implemented in the context of a programming language. Like a REPL, the shell’s command line interface reads a command, evaluates it, prints out the results, and then returns to the shell prompt, in a loop. Unlike a REPL, the shell’s command line interface allows users to access the operating system interface and to run a variety of different programs. For example, the whoami command will tell you your user name:

$ whoami
myusername

The Unix file system stores programs and other files. Users type commands at the shell prompt to run programs, navigate the Unix file system, and manipulate files.

Many commands have command line options, that specify different options or specific behaviors of a command. Many commands also take command line arguments that are used to specify the target of the operation. For example, cp is the copy command that copies one file to another. It takes two command line arguments, the name of the file source to copy and the name of the destination file that will contain the copy.

17.1.1. Unix File System

The Unix file system consists of files and directories. A file stores data such as program source code, program input data, class notes, and binary executable code. Directories store files and subdirectories and are used to add used to organize the set of files stored in the file system.

The Unix file system is organized in a hierarchical tree structure, with a single directory at the top (/) called the root directory. Under it are some main directories holding system content. Some examples are bin that stores system programs that can be run from the Unix command line, lib that stores system library code, and home that stores every user’s home directory into which they can store their own files. Figure 1 shows an example Unix file system directory structure, with two home directories for users sam and sarita.

The unix file system with root directory at top, with example child directories bin, home, lib, and two example subdirectories under home sam and sarita.
Figure 1. The Unix File System is organized as a hierarchy with the root directory at the top, and subdirectories and files arranged underneath.

Note that / is the top-level directory, it has several child subdirectories, including bin, lib, and home. Every directory except the root directory has a unique parent directory; the root directory is the only one without a parent directory.

Every user in the system has their own home directory, which is a subdirectory in /home. Each user’s home directory is the the same name as their username. In Figure we show a few example home directories. Every directory except / has exactly one parent directory. For example, home is the parent directory of sarita, and / is the parent directory of home. Every directory is identified by a unique pathname starting from the root directory. For example, /home/sarita is the pathname of the sarita user’s home directory: the pathname starts at the root directory, /, then follows the home sub-directory of /, and finally the sarita sub-directory of home.

When you first log into a Unix system or start a new shell program, you start out in your home directory. The pwd (print working directory) command prints the directory you are currently in, showing its full pathname starting from the root directory /. For example, here is the output when the user sarita logs in and types, pwd:

$ pwd
/home/sarita

When the user sam logs in and types pwd, here is the output:

$ pwd
/home/sam

17.1.2. File System Commands

Unix commands allow users to move around its directory structure, create and delete files and directories, list the contents of a directory, and to see which directory they are currently in. All actions are relative to the current working directory. For example, if a user creates a new file, the file is created in the user’s current working directory.

The cd (change directory) command changes the current working directory (or to moves into a different directory). The ls (list) command lists the contents of the current directory. The mkdir command is used to create a new directory.

For example, to create a subdirectory named unix_notes in her home directory, and to move into that directory, sarita would enter the following:

$ mkdir unix_notes  # make a new directory named unix_notes
$ ls                # list contents of current directory
 unix_notes/
$ cd unix_notes     # move into the new directory
$ pwd               # print current working directory
/home/sarita/unix_notes

There are many ways to create new files. Often users create new files through using an editor program. A less common way to create an empty new file is using the touch command:

$ touch basics
$ ls
 basics

Since we don’t yet know an editor program, we can add some content to the file using the echo command and appending its output to the basics file (>> appends echo’s output to the specified file, basics in this example). For example:

$ echo "ls: list directory contents" >> basics
$ echo "cd: change directory" >> basics
$ echo "pwd: print working directory" >> basics

The cat command dumps the contents of a file to the terminal. To see the contents of basic after running the echo commands above:

$ cat basics
ls: list directory contents
cd: change directory
pwd: print working directory
File names in Unix

Note that file and directory names in Unix are case sensitive, basics and Basics are two different file names, for example.

Also, although file names can contain space characters, they have to be specified using the escape character before the space character (e.g., hello\ there is the way to name the file "hello there"). As a result, Unix user’s typically do not create files with space characters in their names. Instead, users use _ or - in places where they would want a space in a name (e.g., hello_there).

The wc command counts the number of words, lines, and bytes in a file. For example, to see this information for the file we just created, run:

$ wc basics
 3      11      78 basics

Unix users typically organize their their home directory as a set of directories under which related subdirectories and files are stored. For example, user sam would use the mkdir command to create three subdirectories in his home directory, one for class work, one for projects, and one for personal correspondence:

$ mkdir classes
$ mkdir projects
$ mkdir letters

$ ls
classes/    letters/   projects/

Because this user is taking CS31, they want to create a subdirectory under their classes subdirectory for all their work in this class. To do this they would do the following:

$ cd classes
$ pwd
/home/sam/classes
$ mkdir CS31
$ ls
CS31/
$ cd CS31
$ pwd
/home/sam/classes/CS31

Figure 2 shows what the filesystem looks like after sam runs all of the mkdir commands.

The unix file system after sam creates subdirectories classes, letters, projects, and creates a subdirectory under classes named CS31.
Figure 2. The Unix File System Organization after user sam creates some subdirectories.

Now the sam can move into his CS31 directory when he is working on CS31 course work, and create more subdirectories and files in this directory:

$ cd CS31
$ pwd
/home/sam/classes/CS31

File Pathnames and Navigating the File System

As we have seen, the cd command is used to navigate in the file system, and ls lists the contents of a directory.

Both cd and ls take one command line argument that specifies which directory to change into or list the contents of, respectively. There are two ways to name to a directory location for cd to change to. One is to list the directory as its absolute path name, its name starting from the root directory (/), and the other is to list it as a relative path name, its name from the current working directory.

You can also run both cd and ls with no path name argument. Running cd alone will take you home (to your home directory), and running ls alone lists the contents of the current working directory. Here are a some examples that the user sam tried:

$ cd /home/sam/courses/CS31   # cd with absolute path name
$ pwd
/home/sam/courses/CS31

$ cd                          # cd with no path name  (go home)
$ pwd
/home/sam/

$ ls                          # ls with no path name (list in current directory)
classes/    letters/   projects/

$ cd courses/CS31        # cd with relative path name
$ pwd
/home/sam/courses/CS31

$ ls courses/            # ls with relative path name
CS31/

$ cd /                   # cd with absolute path name (go to root directory)
$ pwd
/

Often users use relative path because they are typically shorter to type (they often are just moving near where they currently are).

Every directory contains two hidden entries that help to navigate directories with the cd command: . is another name for the current directory, and .. is another name for the parent directory of the current directory. You can see these files listed if you use the -a command line option to ls:

$ pwd
/home/sam/classes/CS31
$ ls -a
.   ..

These can be used in both relative and absolute path names, to specify the current directory or the parent’s. Using .. in a path name means go up one directory.

$ pwd
/home/sam/classes/CS31

$ cd ..                 # move up one directory to parent directory
$ pwd
/home/sam/classes

$ cd /bin/../home/sam   # go to sam's home directory in an unusual way
$ pwd
/home/sam

$ cd ./classes/./..     # a wacky example of not going anywhere
$ pwd
/home/sam

Finally, ~ is shorthand for directories in /home. When used alone, ~ is shorthand for the user’s home directory. When when combined with another’s user name ~ refers to the other user’s home directory. Here are some examples run by user sam:

$ cd ~/       # cd into home directory
$ pwd
/home/sam/

$ ls ~/
classes/    letters/   projects/

$ ls ~sarita/
unix_notes/

$ cd ~sartita/
$ pwd
/home/sarita
About the previous example

Often times the system administrator sets up default file and directory permissions on home/ that prevent users from viewing each others home directories and files. On such a system, it may not be possible for Sam to cd into Sarita’s home directory, or list her files with ls as he does in this example.

Copying and Moving Files

The cp command copies one file (or directory) to another, and the mv command moves a file (or directory) from one directory into another one, or it renames a file. Both of these commands take two command line arguments, the source and the destination.

Here are some examples;

$ cd unix_notes
$ cp basics test   # copy the basics file to a new file named test
$ ls
basics test

$ mv test ../blah  # move the test file one directory up and renames it to blah
$ ls
basics

$ cd ../
$ ls
blah   unix_notes/

$ cp -r unix_notes notes_copy  # recursively copy all contents of
                               # of unix_notes directory to new directory
                               # named notes_copy
$ cd notes_copy
$ pwd
/home/sarita/notes_copy
$ls
basics

$ cp basics ../.    # copy basics up a directory to file with same name (/.)
$ cd
$ pwd
/home/sarita/
$ ls
basics unix_notes

Removing Files and Directories

Sometimes you want to remove files and directories. The rm command is used to remove a file, and the rmdir is used to remove a directory. Both take the name of the file or directory to remove. Both have command line options to specific behavior of removing.

Removing files without the -i command line option

By default, the rm command permanently deletes a file. It does not move it to a recycle bin like deleting files on some other operating systems may do. Therefore, rm should be used with caution. Sometimes a system administrator configures rm to automatically use its -i command option by default, so that rm first prints a prompt to give the user a chance to enter n before removing the file (if the user enters y or Y to the prompt the file will be removed, and any other response it will not).

On systems where rm isn’t set up to by default run rm -i, users often add this feature to their shell configuration file. We discuss Bash configuration files more in Section 17.6.

For example (note that if your system isn’t set up with rm using -i by default, you would type rm -i to see this same behavior).

$ ls
 basics unix_notes
$ rm basics
  rm: remove regular file basics? y
$ ls
 unix_notes

$ rm unix_notes
  rm: remove regular file basics? n
$ ls
 unix_notes

By default, rmdir only removes empty directories, a feature that prevents the user from accidentally removing content that they did not intend, by forcing them to explicitly remove all directory contents before removing the directory. Here are some example calls from user sam:

$ cd
$ pwd
/home/sam
$ ls
classes/    letters/   projects/
$ rmdir letters
$ ls
classes/    projects/

$ rmdir classes
rmdir: failed to remove classes: Directory not empty
$ ls
classes/    projects/

A user can recursively remove the contents of a directory using rm -r, and can also forcefully remove files (git rid of all prompting before removing files) by adding the -f option too: rm -rf.

Be very careful with the -f and -r command line options

Great care should be taken when using -f with rm, as the prompting behavior of rm -i often prevents accidental removal of files; if you run rm -rf you can accidentally recursively remove a full directory of files. Because of this, it is best to avoid using these command line options. However, when deleting a large number of files and subdirectories, they are useful. In cases when you do want to use these options, it is good practice to first ensure that you are in the right directory (by running ls and pwd) before running rm -rf.

17.1.3. Basic Commands Summary

Here is a summary of some of the UNIX commands discussed in this section, with examples:

  • pwd — Print working directory: prints out the full pathname of the current directory (cwd).

  • cd <pathname> — Change directory: changes the current directory to be the directory specified by <pathname>. The pathname can be relative to the cwd or an absolute pathname from /.

    • Move into the sub1 directory from the current directory:

      cd sub1
    • Move into the /home/sam directory, regardless of the current directory:

      cd /home/
    • Change to the parent directory of the current directory (i.e., move up one level in the filesystem hierarchy):

      cd ..
    • Change to your "home" directory:

      cd
  • ls — List: list files and directories in the current directory.

  • ls <pathname — List: list files and directories in the directory specified by <pathname>.

    • List the contents of user sam's home directory:

      ls /home/sam
  • mv <p1> <p2> — Move: move/rename file specified by pathname <p1> to <p2>.

    • Rename oldfile to be newfile

      mv oldfile newfile
    • Move newfile into subdirectory sub1:

      mv newfile sub1/
    • Rename sub1 directory to sub2:

      mv sub1 sub2
  • cp <p1> <p2> — Copy: make a new copy of the file specified by pathname <p1> and name the new copy <p2>.

    • Copy oldfile to newfile (oldfile still exists):

      cp oldfile newfile
    • Copy oldfile up one directory to a file also named oldfile (current directory and parent directory both have a file named oldfile, whose contents are identical until one of the files is modified):

      cp oldfile ../.
  • rm <pathname> — Remove: delete the file specified by <pathname>.

    • Delete file named temp in my home directory:

      rm ~/temp
  • mkdir <dir> — Make directory: create a new directory named <dir>.

    • Create a new directory named test in the current directory:

      mkdir test
    • Create a new directory named private in my home directory:

      mkdir ~/private
  • rmdir <dir> — Remove directory: delete the directory specified by pathname <dir> (must be empty).

    • Remove directory named private in my home directory:

      rmdir ~/private
  • wc <file> — Word count: list the number of bytes, words, and lines in a file.

  • touch <file> — Create a new empty file with name <file>.

    • Create a new empty file named my_notes in the current directory:

      touch my_notes
  • cat <file> — Print out contents of <file> to the terminal.

    • Print the contents of the basics file:

      cat basics
  • less <file> — Print out the contents of <file> to the terminal, one page at a time, pausing at each page. The space bar key advances to the next page.

    • Print the contents of the basics file one page at a time:

      less basics
  • more <file> — Another pager (like less) for viewing files one page at at time.

17.1.4. References

For more information see: