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 /home/ubuntu
:
/home/ubuntu/../.././home/ubuntu/
Let's break the above path into its parts:
/home/ubuntu/
- The ubuntu
directory within the home
directory within the root (/
) directory.
../../
- 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
vs. ls /
? What do you think the output of ls ./
would be if you first ran cd /
?
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 ot
.
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 cp
, mv
, mkdir
, touch
, and rm
. Their meanings are listed here:
Command | What it does |
---|---|
cp |
Copy one or more files to a new location |
mv |
Move or rename a file or directory |
mkdir |
Make a new directory |
touch |
Create a new file or update modification time if a file with that name exists |
rm |
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".
mkdir ~/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
Remove the from-home.txt
file.
rm from-home.txt
Remove the 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 children
directory.
cd ~/cli-tmp/parents/children
Create a file named "bob".
touch bob
Move the file named "bob" to the grandchildren
directory.
mv bob grandchildren
Copy the grandchildren
directory to the parents
directory with a new name: nephews
.
cp -r grandchildren ../nephews
Copy the contents of the "nephews" directory to the "children" directory.
cp ../nephews/* ./
View what you've done with the tree
command: tree ~/cli-tmp
. Note that you may need to install the tree
command:
tree
command.
tree
with the sudo yum install tree
command.
tree
is pre-installed on GitHub Codespaces
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 grandchildren
directory.
rm ~/cli-tmp/parents/children/grandchildren/bob
Remove the cli-tmp
directory.
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: ls
, mkdir
, and 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 /bin/echo
.
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 terminates the process by sending it a SIGINT signal.
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 -a
flag.
$ 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
Video Walkthrough
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
Video Walkthrough
What's the difference between abc/
and /abc
?
The path abc/
(also ./abc
and ./abc/
) are paths relative to your current working directory. The path /abc
, however, is the file or directory abc
in the root directory.
Video Walkthrough
What does ../abc mean?
The path ../abc
is a reference to the parent directory (..
), and the file or directory called "abc" within that directory.
Video Walkthrough
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 ./
Video Walkthrough
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/
Video Walkthrough
This exercise isn't a true exercise. It's a review of some common navigation tasks with no questions, solutions, or videos.
To get your current location, use pwd
:
$ 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
/
Use the 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
Use the -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
This exercise isn't a true exercise. It's a walkthrough of some common commands with no questions or solutions. 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
command:
$ 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 rm
command:
Warning!
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
Video Walkthrough