This past week we had a meeting at work about the learning outcomes from our apprenticeship process. One point brought up was how the terminal can be downright daunting to people whose first experience with a computer didn't involve
C:>_. It's easy for me to forget because I first learned to type on an Apple II, and in high school learned Pascal and C++ on old DOS machines that looked like this:
My high school programming teacher Mr Reber used to say "Computers are fast, accurate morons. Humans are slow, error-prone geniuses". Computers will do exactly what you tell them to do, very quickly. If you tell it to do something stupid, its gonna do it. If you tell it to do something that will crash your program, its gonna crash.
Conversely, humans are slow, error-prone geniuses. They make the commands, the tell the computer what to do. My favorite example of this was actually in a math class. The teacher had peanut butter, jelly, and bread, and asked us to command her to make a sandwich. The first person said 'scoop the peanut butter on the knife' so she picked up the knife and bonked it on the lid of the peanut butter jar. We never told her to take the lid off. A computer works the same way - if you forget about the lid its not going take it off first.
What is the terminal?
Okay enough theory, what is the terminal? Simply put, its a way to interact with the computer using text commands instead of a mouse and user interface. The benefits are its extremely fast and can display a LOT of information quickly. The downside is you have to know exactly what you're doing, know how the file system is structured, and know what strange incantations or incense you have to burn to make it do what you want.
Quite often you'll be required to install tools or start local development environments using the command line. Because of this you'll need to understand the basics of moving around the system and executing basic commands in the terminal.
When I try to teach someone about the terminal I always start with three basic commands:
pwd stands for Present Working Directory. Essentially 'where the hell am I?'. Knowing where you currently are in the file system is vital. If you tell it to look for a file or program, you need to know where it is in relation to yourself. Right now if I type 'pwd' in my terminal and pressed enter it would say
/Users/cpeak/Sites/cpeak.github.com. That's because I am currently working in my (cpeak) Sites directory (/Sites), in the folder that contains my personal website (/cpeak.github.com). I could do the same thing in the Finder with my mouse.
Let's open that folder in the Finder and right-click the name at the top of the window. Look familiar? Same as what our pwd command reports. Macintosh HD is the Root level( / ), then /Users, /cpeak, /Sites, and finally /cpeak.github.com.
cd stands for Change Directory. This is why you need to understand how a directory tree works. All files on your system 'branch out' from the root level. Just like before, I am in my personal website directory. Let's jump back to the Sites directory which is one level up. I can do this a few ways. I could type
cd /Users/cpeak/Sites which explicitly tells the computer where to go (note the leading /). I could type
cd .. which is a shortcut to jump up one level. I could also type in
sites which is a shortcut I specifically set to jump right to my Sites directory, more on that later.
I can also change directories relative to where I am. I'm currently in my cpeak.github.com directory. Lets say I wanted to go into the images folder, I would type
cd images. Since I didn't start with a / the computer will look in the present working directory. It would be the same as typing
ls will list the content of the present working directory. Well, almost everything. The system has hidden files that start with a . which are important. To see everything type
Okay, lets see it all in action. Here I type use the pwd command to find out I am in my home directory. Then I cd into Sites/cpeak.github.com. I type in ls to list all the files, but realize I need to see if there are hidden ones so I type ls -a. You can see the second ls command shows .git, .gitignore, and a few others.
Drag-and-drop to change directories
If you really aren't sure what a folder's path is and need to
cd into it, one handy trick is to type cd (space) and then drag the folder into the Terminal. It will autocomplete the full path of the folder so you can hit enter and that becomes your pwd.
Tab to autocomplete
When navigating around your system using the terminal a huge time saver is using Tab to auto complete things. Lets say I am in my Home directory, and type
cd Sites/bus then tap Tab, it will autocomplete 'business-card-generator'. As long as the first few letters are unique it will work. Lets say I was still in the Home directory, but this time typed
cd Sites/g and tapped Tab - the system will sound an alert because there are directories named 'gallery' and 'gorilla-studios.com'. Whenever this happens just hit Tab again and it will display the options for what you are trying to autocomplete.
Most people use the default Terminal.app built into OS X, but I prefer to use iTerm 2 for a few reasons. The main reason I love iTerm is a global hot key to pull the application up as a full screen overlay. If I hit
Control + t the window pops up no matter where I am in the Finder. It's super fast and I don't have to Command Tab through my open applications to find it. If you don't use VIM or a terminal based editor this probably isn't that important.
The most beneficial thing I've learned about working in the terminal is custom shortcuts. You can define your own command shortcuts in your bash profile (don't make me explain bash profiles or PATHs, they make me angry and confused). To do this, add a line that reads 'alias shortcut=command'. 'shortcut' can be whatever you want, and 'command' has to be a valid terminal command. Here is some of mine:
The ones I use most are
sites to automatically jump back to my Sites directory where I keep all my local development projects,
gst for git status, and
jek to startup a Jekyll server. A fun one I added recently is
please - sometimes the terminal will require Admin authorization for certain commands, so 'please' will apply
sudo !! which means execute the last command as superuser.
prune saves a lot of time because I can never remember 'git remote update origin --prune'. This updates all the branches in my working git repository, removing any that were deleted and adding any new ones.
One of my all time favorite plugins is git-completion.bash. This allows you to tab-complete Git branch names, saving time when checking out or committing to branches. I'm honestly baffled why this isn't part of Git out of the box. Saves a lot of time and frustration if you can't spell like me.
Just with any skill, practice makes perfect. There is a ton of command line things I don't even know, but getting the basics down is important. Play around with your terminal, try navigating through various parts of the file system and seeing if you can keep track in your head where you are. It takes some time to get that mindset, but once you can understand it, it makes the computer a little less frustrating.