In a desktop environment, like that of OS X, you have windows, menu bars, and the desktop to give context to what you are doing. In the command line, however, the context is solely the file system. In fact, files and directories are what make up the command line. Almost everything you do at the prompt will deal with files. Every time you type a command, you are telling the computer to execute a file.
Not only does the file system provide context for you when you're trying to work on or get information about files and directories, it also provides context for the commands you run. For example, you can use the
ls command to list the files in a directory. When you run the command by itself, it uses your current directory as context, and lists the files that are in the directory you are in.
Let's look for a moment at some of the symbols that will help us navigate the command line:
/- The root directory or a separator when listing directories
.- The current directory (also
./) or the same level
..- The directory one level up (also
../..- The directory that is two levels up; that is, the directory that is one level up from
~- Your "home" directory, or the directory you are placed in when you log in.
*- The "splat" or "glob" operator. This is the wildcard of the command line and represents "any characters."
The above symbols can be combined with directory and file names to represent their locations. The path
/home/ubuntu can be dissected as follows:
root directory + "home" directory + directory separator + "ubuntu" (user) directory
While it may not make sense to do so, somewhat "nonsensical" combinations can represent valid paths. The following path is the same as
Let's break the above path into its parts:
ubuntudirectory within the
homedirectory within the root (
../../- Up two directories (which takes us back to the root directory).
./- The same directory (which is still
home/ubuntu/- Back down into the home directory, then the ubuntu directory.
Note that there's a dramatic difference between a path that starts with a leading slash vs one that doesn't. For example:
/home/ubuntu This path specifies a folder called
ubuntu that lives in a directory called
home, which is itself in the root directory.
home/ubuntu This path specifies a completely different folder. This path means there's a folder called
ubuntu that lives in a directory called
home, which is itself in the current directory.
The leading slash makes all the difference. Make sure to pay careful attention to that whenever you're looking at paths.
Navigating your computer's file system is pretty easy with the help of the File System Legend above, and a few simple commands:
cd- change directory
ls- list files
pwd- display the current working directory
Let's get a feel for navigating the command line interface by opening up Terminal or logging in to your managed server or virtual machine and treading water for a bit. After logging in, type the following commands and note what happens after each step:
# Change directory (with no arguments) $ cd $ pwd /home/ubuntu # Change to root directory $ cd / $ pwd / # Change directory (with no arguments again) $ cd $ pwd /home/ubuntu # Go up one directory $ cd ../ $ pwd /home # Show files and directories (with no arguments, it uses current directory) $ ls ubuntu # Navigate into "ubuntu" directory $ cd ubuntu $ pwd /home/ubuntu # Change to ~ (home) directory $ cd ~ $ pwd /home/ubuntu # Show files and directories in root directory $ ls / bin boot dev etc home lib lib64 media mnt opt proc root rootfs run sbin selinux srv sys tmp usr var # Show files that match a certain pattern # using the splat operator (asterisk) # The following example may not produce the same # results on your system. On some systems, such as # Ubuntu, you may need to use `sudo ls /*ot` instead # of ls /*ot, but on others, such as a Mac, you # will only get error messages. What's important # here is to learn how to use the commands, not # replicate the results. $ ls /*ot boot root
Did you notice that typing
cd by itself takes you to your "home" directory? Which command(s) made you "descend" into a directory? Which command(s) made you go up a directory? What was the difference in the output of
ls /? What do you think the output of
ls ./ would be if you first ran
The last example shows that the splat (
*) allows you to list files that match a pattern. The asterisk is the wildcard and represents any number of any characters, so
*ot represents any file or directory that ends in
With an understanding that "where you are" in the command line provides context for your commands, and a working knowledge of navigating the command line interface, we can move on to learning to manage files and directories from the command line.
When you open up Finder in Mac or Windows Explorer in Windows, you can see manila-folder-style directories along with icons that represent documents, images, and programs. Think for a moment about some of the things that you do with the files from time to time. Do you ever move files around? Maybe sometimes you copy a file so that you can make a new version. Have you made new directories before? It's probably not too surprising by now that you can do the same things from the command line. Some of the most frequently used commands for managing files and directories on the command line are
rm. Their meanings are listed here:
|Command||What it does|
||Copy one or more files to a new location|
||Move or rename a file or directory|
||Make a new directory|
||Create a new file or update modification time if a file with that name exists|
||Remove one or more files or directories|
To get acquainted with these commands, go ahead and try them out. Try the following exercises to solidify your understanding of the above commands:
Create a directory in your home directory called "cli-tmp".
From the home directory, create a file in the cli-tmp directory called "from-home.txt".
cd touch cli-tmp/from-home.txt
Navigate to the cli-tmp directory, then create a file called "in-cli-tmp".
cd cli-tmp touch in-cli-tmp
Try to make a directory called "in-cli-tmp" within the
cli-tmp directory. What happens?
$ mkdir in-cli-tmp mkdir: in-cli-tmp: File exists
cli-tmp directory (hint use
man to see how to remove a directory recursively).
cd rm -r cli-tmp
Create a nested set of directories in your home directory: cli-tmp > parents > children > grandchildren (hint: use the
-p flag to do it all at once).
mkdir -p ~/cli-tmp/parents/children/grandchildren
Navigate to the
Create a file named "bob".
Move the file named "bob" to the
mv bob grandchildren
grandchildren directory to the
parents directory with a new name:
cp -r grandchildren ../nephews
Copy the contents of the "nephews" directory to the "children" directory.
cp ../nephews/* ./
View what you've done with the
Note: You may need to install the
tree command using homebrew or a similar tool if you are on a Mac. On Cloud9, you can install it using
sudo yum install tree. If that doesn't work, try
sudo apt-get install tree.
$ tree ~/cli-tmp /Users/[username]/cli-tmp/ └── parents ├── children │ ├── bob │ └── grandchildren │ └── bob └── nephews └── bob
Remove the "bob" file from the
cd rm -r cli-tmp
In the last chapter, we talked about the anatomy of commands, which was basically "command plus arguments." But what is a command really? As mentioned at the beginning of this chapter, a command is just a file. That's right:
cd are all files. Files that can be used as commands are called executables. Not all files are executables.
What makes an executable different from other files?
To run an executable, you just type its path as the first part of your input, then type in your arguments, and hit enter, like this:
$ /bin/echo "Hello World" Hello World
In the above example,
/bin/echo is the path to the executable, and
"Hello World" is the first (and only) argument.
If you want to execute a file in your current directory, you have to type
./ or the path to your current directory before the filename. For common or installed commands, you won't usually have to specify the path of the executable because the command line interface already knows where to find it. That's why you can type
echo instead of
When you use the
echo executable, it will probably take no more than a few milliseconds to run, and the chances that it will freeze or get stuck are almost zero. Some executables, however, cause long-running processes, and it is useful at times to be able to exit out of them before they exit on their own. Some commands and executables run in a loop, and won't exit until you tell them to. Others freeze or take a lot longer than you expected, and need to be stopped short. On Unix-like systems, there is an almost ubiquitous way of exiting out of any executable's process:
Ctrl + c. This key combination sends a signal to the process to terminate
If you are using Bash commands and accidentally create an infinite loop, you can exit out of it with
Ctrl + c:
$ while true; do echo 'Hit CTRL+C'; sleep 1; done Hit CTRL+C Hit CTRL+C Hit CTRL+C
The above will echo "Hit CTRL+C", then sleep for a second, until you hit
Ctrl + c on your keyboard.
Note the format "Ctrl + c" means "hold down the control key, then press c, and release." You'll see other combinations like this as you learn more about programming and about using Bash.
In the next chapter, we'll discuss how the command line knows where installed commands are located.
List the hidden files in a directory.
You can list all files, including hidden ones, in a directory using the
$ ls -a . .bash_history .bash_profile .cache .gem .npm .. .bash_logout .bashrc .config .local .profile
To only list hidden (also called dotfiles) files, you can use the following command:
$ ls -d .* . .bash_history .bash_profile .cache .gem .npm .viminfo .. .bash_logout .bashrc .config .local .profile .ssh
List the files in the parent directory. Then list the files in the parent directory's parent directory.
You can list a parent directory's files using the following command:
$ ls .. ubuntu
What happens if you run that command from the root directory?
$ cd / $ ls .. bin home lib64 opt sbin usr boot initrd.img lost+found proc srv var dev initrd.img.old media root sys vmlinuz etc lib mnt run tmp vmlinuz.old
As you can see, since the root directory doesn't have a parent directory, it just prints out the files in the root directory itself.
To list the files of the parent's parent directory, just add a slash and an extra
$ cd $ ls ../.. bin home lib64 opt sbin usr boot initrd.img lost+found proc srv var dev initrd.img.old media root sys vmlinuz etc lib mnt run tmp vmlinuz.old
What's the difference between
./abc/) are paths relative to your current working directory. The path
/abc, however, is the file or directory
abc in the root directory.
What does ../abc mean?
../abc is a reference to the parent directory (
..), and the file or directory called "abc" within that directory.
Suppose you are in a directory with 7 files. You need to move 6 of them into a "tmp" directory, that you have yet to create. How do you do that?
Let's break this up into a few steps:
First, create the temporary directory:
$ mkdir ~/tmp
The fastest way to move all but one file is to move all the files, then move the one file back. Assuming the one file that you don't want to move is
1.file, the following commands will do the trick:
$ mv * ~/tmp $ mv ~/tmp/1.file ./
Suppose you have two directories called xyz/ and abc/. How do you move all the files in abc/ that end with ".txt" into xyz/?
Using the glob operator
*, (also known as the wildcard or just asterisk) you can move all files that match a particular pattern. First, check your pattern:
$ ls abc/*.txt 1.txt 2.txt 3.txt
Then move the files:
$ mv abc/*.txt xyz/
Let's review some common navigation tasks:
To get your current location, use
$ pwd /home/ubuntu
To change your current directory, use
cd. Using it without any arguments will take you to your home directory:
$ cd $ pwd /home/ubuntu
You can also pass the
$HOME variable as an argument, or use the
~ (tilde) as the first argument to achieve the same results:
$ cd $HOME $ pwd /home/ubuntu $ cd ~ $ pwd /home/ubuntu
Go to the root directory (
$ cd / $ pwd /
ls command to determine what files and directories are located in the current directory:
$ cd / $ pwd / $ ls bin dev home lib64 lost+found mnt proc run selinux sys usr boot etc lib local media opt root sbin srv tmp var
Pass a directory or a path as an argument to the
cd command to go directly to that location:
$ cd usr $ pwd /usr
You can also get a sneak peek into what directories are located in a specific path:
$ cd / $ pwd / $ ls usr bin etc games include lib lib64 libexec local sbin share src tmp
-lah set of flags as arguments to the
ls command to get more detailed information about files and directories:
$ cd / $ ls -lah total 112K dr-xr-xr-x 24 root root 4.0K Mar 16 20:56 . dr-xr-xr-x 24 root root 4.0K Mar 16 20:56 .. -rw-r--r-- 1 root root 0 Mar 16 20:56 .autofsck dr-xr-xr-x 2 root root 4.0K Oct 1 2014 bin dr-xr-xr-x 3 root root 4.0K Oct 1 2014 boot drwxr-xr-x 16 root root 2.8K Jun 3 21:48 dev drwxr-xr-x 76 root root 4.0K Jun 3 21:48 etc drwxr-xr-x 3 root root 4.0K Sep 29 2014 home dr-xr-xr-x 7 root root 4.0K Mar 25 2014 lib dr-xr-xr-x 10 root root 12K Oct 1 2014 lib64 drwxr-xr-x 2 root root 4.0K Mar 25 2014 local drwx------ 2 root root 16K Mar 25 2014 lost+found drwxr-xr-x 2 root root 4.0K Jan 6 2012 media drwxr-xr-x 2 root root 4.0K Jan 6 2012 mnt drwxr-xr-x 3 root root 4.0K Mar 25 2014 opt dr-xr-xr-x 75 root root 0 Mar 16 20:56 proc dr-xr-x--- 3 root root 4.0K Jun 3 21:48 root drwxr-xr-x 4 root root 4.0K Sep 29 2014 run dr-xr-xr-x 2 root root 12K Oct 1 2014 sbin drwxr-xr-x 2 root root 4.0K Jan 6 2012 selinux drwxr-xr-x 2 root root 4.0K Jan 6 2012 srv dr-xr-xr-x 13 root root 0 Mar 16 20:56 sys drwxrwxrwt 3 root root 4.0K Jun 10 03:34 tmp drwxr-xr-x 13 root root 4.0K Mar 25 2014 usr drwxr-xr-x 19 root root 4.0K Mar 25 2014 var
In this exercise we're going to play with executables. We'll find the location of so-called "default executables" by using the
which command, then execute a file using its absolute path.
To figure out a default executable's location, you can use the
$ which touch /bin/touch
Now we can execute the
touch command using its full path or name:
$ cd $ touch test $ ls test $ /bin/touch test2 $ ls test test2
We can do the same thing now with the
The "rm" command is extremely dangerous. There is no easy, or even moderately difficult, way to restore what you delete with the "rm" command!
$ cd $ rm test $ ls test2 $ which rm /bin/rm $ /bin/rm test2 $ ls $