What you call a folder in a GUI is a directory on the command line. They mean the same thing. A GUI gives you folders and a few other ways to organize your stuff, like documents, photos, spreadsheets, and music. On the command line, the primary way to organize stuff is with directories.
Directories are for organizing your stuff
In a GUI, there are folders dedicated to your documents, your desktop, your computer’s applications, and other stuff. In other words, a GUI provides folders for you to organize and find your stuff.
Or you don’t have to. A GUI file manager, like macOS Finder and Windows Explorer, has other ways for you to find your stuff. For example, you can just search for that last document you worked on. Forget where something is? No problem, just search for it. It’s in there somewhere, let the GUI worry about it.
You don’t get it quite as easy with the command line. There are no guardrails, remember? So it’s important to keep your stuff in order. And the best way to do that is to use directories.
Step 0: You’ll need a command line
Is this your first time on the command line? Take a guided tour first.
You’ll need access to a computer that has a command line.
Do this: Install Tech Writer Tools.
Step 1: Working from home
We’ll start with your current directory. The current or working directory is just the command line’s idea of a default directory. When you don’t specify a directory for a command, the command assumes that you mean the current directory. Another way to look at this is that little red dot on a map, “You are here”. Your current directory is your current location in the computer’s file system. You can point to other locations (directories), too. But when you’re not pointing somewhere specific, a shell command assumes you mean your current location.
By the way, we’ll use the term sub-directory once in a while. There’s nothing special about a sub-directory, it’s just a directory like any other. The “sub-” in “sub-directory” only means that a directory happens to be in another directory.
Now, with your Terminal app showing a shell that’s eager for your next command, let’s make sure you’re starting in the right place. As a matter of good habit, you should be working in your home directory or one of its sub-directories.
Your home directory is the directory dedicated to you, where you put your projects, documents, and your other work (and fun) stuff. There are other directories on your computer for things like applications. These directories are not meant for your stuff, so we’ll stay out of them.
Do this: Enter cd.
techwriter:~$ cd
techwriter:~$ ▮
What happened: The cd command changes your current directory, aka working directory.
When you enter cd by itself, it sets your current directory to your home directory. This is handy when you just want to go back “home” quickly. We’ll cover how to change to a specific directory later.
Step 2: Where am I?
How do you know that cd switched you to your home directory? Look at the shell’s prompt.
techwriter:~$ ▮
The item after the colon (:) is your current directory, which is a tilde (~). You’re not really in a directory named ~, this is just the shell’s shorthand for your home directory.
You can also get the full path for your workding directory. Later we’ll cover what path means exactly.
Do this: Enter pwd.
techwriter:~$ pwd
/home/techwriter
techwriter:~$ ▮
What happened: The pwd command outputs your present working directory. In this case, your current directory is your home directory, which is /home/techwriter.
Notice that the prompt also starts with techwriter. This is your username in Tech Writer Tools. This is not a coincidence, it’s an intentional convention to name home directories after usernames. macOS, Windows, and Linux (which Tech Writer Tools is based on) all follow this convention in one way or another.
Step 3: What’s here?
Let’s see what’s in your home directory.
Do this: Enter ls.
techwriter:~$ ls
welcome.txt
techwriter:~$ ▮
What happened: The ls command outputs the names of files and sub-directories in a directory. By itself, ls outputs all file names and sub-directory names in the current directory.
In this case, there’s a lone file in your home directory at the moment, welcome.txt.
Step 4: Make a directory
Now let’s make a directory.
Do this: Enter mkdir donuts.
techwriter:~$ mkdir donuts
techwriter:~$ ▮
What happened: The mkdir command makes a directory. Unlike cd and ls, mkdir requires an argument, which is a name for the new directory.
Also, notice that mkdir doesn’t output anything (unless there’s an error). Most command line tools are pretty terse, especially the fundamental commands that do simple operations. The rationale is that it makes the commands easier to work with, since they reduce the clutter of your interactions. The command line is all about being more interactive so, ironically, commands try to stay quiet unless there’s something exceptional to report, like an error.
Let’s confirm that your new directory exists.
Do this: Enter ls.
techwriter:~$ ls
donuts welcome.txt
techwriter:~$ ▮
There you go, your new sub-directory donuts is ready for organizing your tasty treats.
You might also notice that donuts has a different colour than welcome.txt. And that’s all it is, you can’t add colour to a specific file or directory’s name explicitly. Names are text only. This colour is from the ls command to give you a visual indication of the item’s type. For example, directory names might be in blue while file names might be white.
Naming files and diectories
They say the 3 hardest things in computer science are:
- Off-by-1 errors
- Naming things
Just a few tips about choosing names for your files and directories on the command line:
- Don’t use spaces, tabs, or return characters in the names of files and directories. Yes, the command line allows these characters in file names, but it makes interacting with them kinda tedious.
- Linux-like command lines technically allow these characters, but you will live a happy life if you personally refuse to use *, ?, /, \, >, <, :, | in a name.
- While you’re at it, avoid punctuation generally except for underscore (_), hyphen (-), and full stop (.).
- Uppercase and lowercase letters are distinct. For example, these are all different: Banana, banana, BANANA, and orange. (Orange you glad I didn’t use bAnAnA?)
- Generally, use letters and digits that you can easily type from your keyboard. The biggest reason is that it makes it easier to interact with the command line. You can certainly use characters like emojis, but you’d be slowing down your interaction and there still exist old-school command line tools that aren’t aware of fax machines let alone 💩.
Step 5: Specific files and directories
You’ve used the ls command by itself, which tells ls to list the names of files and sub-directories in the current directory. The ls command has ways to list specific names, too. You just have to give it an argument.
Let’s start with just a name. Give ls a name and it’ll list that file or directory.
Do this: Enter ls welcome.txt.
techwriter:~$ ls welcome.txt
welcome.txt
techwriter:~$ ▮
What happened: You asked ls to list names of files and sub-directories that matched its argument. In this case, only one file matched, naturally, so ls showed it.
You know what’s tasty? Dosa. Is there something in the current directory for that?
Do this: Enter ls dosa.
techwriter:~$ ls dosa
ls: cannot access 'dosa': No such file or directory
techwriter:~$ ▮
What happened: ls let us know that there was no matching file or directory named dosa. No surprises.
Do this: Enter ls donuts.
techwriter:~$ ls donuts
techwriter:~$ ▮
What happened: Nothing, apparently. But something did happen. When we give a directory name to ls, it lists the files and sub-directories in that directory. Since the donuts directory is empty, there’s nothing to list.
To make things interesting, let’s make a copy of the welcome.txt file.
Do this: Enter cp welcome.txt welcome2.txt.
techwriter:~$ cp welcome.txt welcome2.txt
techwriter:~$ ▮
What happened: The cp command copies files. We’ve given it 2 arguments, a source and a destination. In our case, it copied the source file, welcome.txt, to another file with the name of the destination, welcome2.txt.
Do this: Confirm the existence of welcome2.txt with the ls command.
Another thing you can do is use ls to list more than one file or directory. For example, you can list all files and directories with names that end with .txt.
If you know what these files are ahead of time, you can just enter their names explicitly.
Do this: Enter ls welcome.txt welcome2.txt.
techwriter:~$ ls welcome.txt welcome2.txt
welcome.txt welcome2.txt
techwriter:~$ ▮
What happened: The ls command accepts multiple arguments. You asked it to list two specific files, and it did as you asked. In fact, when it makes sense, most command lines tools accept multiple file or directory names as arguments.
Step 6: Globbing
Yeah, I know, “glob” is a weird word, probably weirder if you don’t know what it means. Let’s get into that.
What do you do if you don’t know what all the files ending with .txt are? Or what do you do if there are too many to enter without cramping your fingers? The answer to both of these questions is pattern matching in the shell, also known as “wildcards”.
Do this: Enter ls *.txt.
techwriter:~$ ls *.txt
welcome.txt welcome2.txt
techwriter:~$ ▮
What happened: The command output all files and directories in the current directory that end with .txt. In our case, there are two files that match, welcome.txt and welcome2.txt.
The asterisk * means “match anything that is zero or more characters”. In our case, the * happens to match the welcome in welcome.txt and welcome2 in welcome2.txt.
The “zero” in “zero or more” is something to point out. What this means is that if the rest of the pattern matches, then ls will output the name as if the * isn’t there at all.
Let’s see what this means.
Do this: Enter ls welcome*.txt.
techwriter:~$ ls welcome*.txt
welcome.txt welcome2.txt
techwriter:~$ ▮
What happened: The welcome*.txt pattern means “match all names that begin with welcome, possibly has some characters, then ends with .txt”. In the case of welcome.txt, the * matched zero characters while the rest of the pattern still matches.
You might already be familiar with regular expressions and recognize the use of *. Globbing is a kind of way to use regular expressions in the shell, but it works differently than conventional regular expressions, both in syntax and the way that the shell handles it.
For syntax, globbing uses the * to mean “zero or more of any character”. But in regular expressions, the * means “zero or more of the preceding item”.
In practice this means that donut* in the shell means “match items that begin with donut and possibly ends with other characters”. That would match files and directories with names like “donuts”, “donutty”, and plain “donut“.
In a regular expression, donut* means “match text that begins with donu followed by zero or more t characters. That would match text like “donut”, “donuttttttt”, and “donu” (no “t”).
Get it? Give this a think for a bit: Globbing syntax is subtly different than regular expression syntax.
As for how the shell handles globbing, here’s the other subtle but important part: when you use * in the shell for an argument, the command that acts on the globbing never sees the *. Before the shell passes your arguments to a command, the shell expands the * to insert all the matching names, then passes those names to the command.
So when you entered ls *.txt earlier, here’s what the shell did:
- The shell looked for all files and sub-directories in the current directory that match *.txt. In this case, those files are welcome.txt and welcome2.txt.
- The shell expanded that single argument, *.txt into 2 arguments, welcome.txt and welcome2.txt.
- The shell ran your command, ls, with expanded arguments.
Bottom line: the ls command never saw the *.txt argument. The shell only gave it the expanded arguments. And this is what’s called globbing.
Now you might be asking, “Well what’s the point of the ls command if the shell’s globbing did the heavy lifting?”
Good question. My answer has two parts:
- The ls command can do other things for you with the names of files and directories, like adding colour, as we saw earlier.
- More usefully, the shell’s globbing is universal. It applies it consistently to any command that you enter. That adds a lot of expressiveness to your commands.
We can see an example of this easily.
Do this: Enter echo *.txt
techwriter:~$ echo *.txt
welcome.txt welcome2.txt
techwriter:~$ ▮
What happened: The echo command just outputs its arguments verbatim, without processing them. It’s useful in scripts to report information, status, results, and so on. As we can see, the shell did indeed expand *.txt and passed the names of those matching files to echo, which dutifully output its arguments verbatim.
Step 7: Follow the path
We mentioned the idea of the path earlier when we saw that your home directory’s path is /home/techwriter. We use paths as a way to refer to files and directories that aren’t in the current directory.
Think of a path as a series of steps to follow to get to a specific location in the file system. We can see how this works by manually following the path of your home directory, /home/techwriter.
Our path starts with / so let’s start there.
Do this: Enter cd /.
techwriter:~$ cd /
techwriter:/$ ▮
What happened: The cd command put us in the directory named /, as we can see in the prompt. You can also confirm this with pwd if you want.
Do this: Enter pwd to see your current directory.
The plain ol’ / directory is the top directory in the file system. We give it a special name, root. The shell never displays root as a name explicitly, it’s just a convention for people to refer to top of the file system.
(Yeah, everyone knows the inconsistency of naming the top of something as root. It’s part historical accident and part something that computer scientists are fine with, so the name has stuck for the past few dedades.)
The path separator is the character that we use in a path to separate each “step” in a path, where each step is the name of a directory. In Linux-like systems like Tech Writer Tools and macOS, this separacter character is the forward slash, /. In Windows, it’s the backward slash, \. Be careful not to confuse the two.
Now let’s see what’s in the root directory.
Do this: Enter ls.
techwriter:/$ ls
bin etc lib mnt proc run srv tmp var
dev home media opt root sbin sys usr
techwriter:/$ ▮
What happened: These are all the files and sub-directories in the root directory. There are a bunch. For example, the bin directory contains commands, etc contains configuration information for your computer.
Do you see the directory named root? I just told you that the shell doesn’t explicitly show the name of the root directory. I’m still right. This directory is named root because it’s actually a special directory, the home directory for the superuser. The superuser is a special user account for the system administrator. The name is root for historical reasons and we can ignore it.
Now let’s go to the home in /home/techwriter.
Do this: Enter cd home.
techwriter:/$ cd home
techwriter:/home$ ▮
What happened: We’re now in /home, as our prompt reminds us.
Do this: Enter ls.
techwriter:/home$ ls
techwriter
techwriter:/home$ ▮
What happened: There’s only one item in home, and that’s the techwriter directory, our home directory. Let’s go to it.
Do this: Enter cd techwriter.
techwriter:/home$ cd techwriter
techwriter:~$ ▮
What happened: We’re in our home directory, safe and sound.
Step 8: Dots that are directories
There are a couple of special directories in every directory. Like ~, they are shorthand, convenient ways of referring to specific directories.
We can see them with the ls command.
Do this: Enter ls -a.
techwriter:~$ ls -a
. .. .bash_profile .bashrc donuts welcome.txt welcome2.txt
techwriter:~$ ▮
What happened: We gave ls an option, -a. This option tells ls to list all items. (Actually, all it does is tell ls not to ignore items with names that begin with a . character.
Look closely. Notice the . and .. items. They’re directories.
Also, notice .bash_profile and .bashrc. As their colour indicates, these are files. Conventionally, Linux-like systems use so-called dot files for a user’s configuration and preferences. These particular files specify your settings for the shell.
Let’s get back to the . and .. directories.
First, there’s the directory named ., which is a single full stop character. This is the shorthand way to refer to the current directory in a path.
Then there’s the directory named .., which is 2 consecutive full stop characters. This is the shorthand way to refer to the current directory’s parent.
Let’s see what this means.
Do this: Enter ls welcome.txt.
techwriter:~$ ls welcome.txt
welcome.txt
techwriter:~$ ▮
What happened: As before, the ls command shows welcome.txt in the current directory.
Do this: Enter ls ./welcome.txt.
techwriter:~$ ls ./welcome.txt
techwriter:~$ ▮
What happened: Essentially, we’ve just entered a similar-meaning command. The path ./welcome.txt means “from the current directory, continue followling the path to welcome.txt”.
The . directory is useful to make things clearer. For example, some commands don’t use the current directory as a default, they might have their own default directory. For commands like this, you can explicitly specify the current directory with ./.
Now let’s try the .. directory.
Do this: Enter cd donuts
techwriter:~$ cd donuts
techwriter:~/donuts$ ▮
What happened: We’re in the donuts directory now.
Let’s do something in the parent of the donuts directory without changing our current directory.
Do this: Enter ls ../welcome.txt.
techwriter:~/donuts$ ls ../welcome.txt
welcome.txt
techwriter:~/donuts$ ▮
What happened: The ls command showed us welcome.txt in the parent directory of our current directory.
The path ../welcome.txt means “from the current directory, go to its parent then continue followling the path to welcome.txt”.
Take a look at the prompt before and after this command, notice that our current directory never changed even though we referred to a directory outside of it.
Do this: Enter cd ..
techwriter:~/donuts$ cd ..
techwriter:~$ ▮
- What happened: We went up one directory, which is back at our home
- directory.
It’s useful to remember that every directory has a . directory.
And every directory except the root directory has a .. directory. I’ll let you figure out why.
Step 9: It’s not all relative
There are also 3 types of path, and we’ve been using both of them:
- Absolute: The path starts at the root directory.
- Relative: The path starts at the current directory.
You can easily tell the difference between an absolute and relative path by its first character. An absolute path begins with the path separator, /. A relative path begins with a sub-directory or file name.
Some examples of absolute and relative paths we’ve seen and used:
- /: Absolute path
- /home/techwriter/donuts: Absolute path
- donuts: Relative path
- ../welcome.txt: Relative path
An absolute path is useful when you want to be absolutely (ahem!) specific about the location of a file or directory. The path always starts at the root directory, so there’s no ambiguity.
But that can be inflexible sometimes. Sometimes it’s useful to specify a file or directory in relation to the current directory as a starting point instead.
Do this: Use the cd and ls commands on a few relative and absolute paths.
You did it!
Congratulations, you know how to work with directories.
What you learned
- Your current directory is the command line’s default directory. When you don’t specify a directory explicitly, the command line assumes your current directory.
- You can change the current directory with the cd command and a directory to change to. Entering cd by itself sets your current directory to your home directory.
- Your home directory is where you (should) store your work and personal files. Other directories on your computer are intended for applications, system settings, and so on.
- You can see what’s in a directory with the ls command. Enter ls by itself to see the names of files and sub-directories. Enter ls with one or more arguments to see the names of specific files and directories.
- Use the * in a command line argument to match any files or directories with matching names. The * means “any combination of 0 or more characters”.
- The shell expands arguments with * to all the matching names, then passes these globbed names to the command.
- You can get the full path of your current directory with the pwd command.
- A path is a sequence of directory names separated by the forward slash (/). A path gives a route to follow to specify a location in the file system. You can use a path when you want to refer to something that isn’t in the current directory.
- The tilde (~) is the shell’s shorthand for your home directory.
- Use the single period (.) as a shorthand for the current directory.
- Use a double period (..) as a shorthand for the current directory’s parent directory.