Learn to Love the Command Line

“Then the interface-makers went to work on their GUIs, and introduced a new semiotic layer between people and machines. People who use such systems have abdicated the responsibility, and surrendered the power, of sending bits directly to the chip that’s doing the arithmetic, and handed that responsibility and power over to the OS.”
—Neal Stephenson, In the Beginning was the Command Line

Many of us here at Tech Connect are fans of the command line. We’ve written posts on configuring a local server, renaming files en masse, & using the Git version control system that are full of command line incantations, some mysterious and some magical. No doubt; the command line is intimidating. I’m sure most computer users, when they see it, think “Didn’t we move beyond this already? Can’t someone just write an app for that?” Up until about a year ago, I felt that way, but I’ve come to love the command line like Big Brother. And I’m here to convince you that you should love the command line, too.

Scripting

So why use a command line when you can probably accomplish almost everything in a graphical user interface (GUI)? Consider the most repetitive, dreary task you do on a daily basis. It might be copying text back-and-forth between applications over and over. You might periodically back up several different folders by copying them to an external drive. We all have repetitive workflows in dire need of automation. Sure, you could write some macros, but macros can be brittle, breaking when the slightest change is introduced. They’re often tricky to write correctly, so tricky that the blinking square at the start of the command prompt is starting to look promising.

One of the first joys of the command line is that everything you do can be scripted. Any set of steps, no matter how lengthy and intricate, can be compiled into a script which completes the process in a matter of seconds. Copy a dozen folders in disparate locations to a backup drive? No problem. Optimize a web app for deployment? A script can minify your JavaScript and CSS, concatenate files, optimize images, test your code for bugs, and even push it out to a remote server.

Available Software

It may seem odd, but moving to the Neanderthal command line can actually increase the amount of software available to you. There are lots of programs that don’t come with a graphical interface, either because they’re lightweight tools that don’t require a GUI or because their author knew that they’d be used almost exclusively by people comfortable with the command line. There are also many software packages that, while they have GUIs available, are more powerful on the command line. Git is a good example: there are numerous graphical interfaces and most are quite good. But learning the commands opens up a wealth of options, configurations, and customizations that just do not exist graphically.

Tying It All Together

There are many wonderful GUIs that allow you to do complex things: generate visualizations, debug code, edit videos. But most applications are in their own separate silos and work you do in one app cannot be easily connected to any other. On the command line, output from one command can easily be “piped” into another, letting you create long chains of commands. For instance, let’s say I want to create a text document with all the filenames in a particular directory in it. With a file manager GUI, this is a royal pain: I can see a list of files but I can only copy their names one by one. If I click-and-drag to select all the names, the GUI thinks I want to select the files themselves and won’t let me paste the text of their names.

On the command line, I simply write the output of the ls command to a file: [1]

ls -a > filenames.txt

Now filenames.txt will list all the files and directories in the current folder. The > writes the output of ls -a (list all files) and it’s one of a few different methods that redirects output. Now what if I want only filenames that contain a number in them?

ls -a | grep [0-9] > filenames-with-numbers.txt

I already have a list of all the file names, so I “pipe” the output of that command using the vertical bar | to grep, which in turn outputs only lines that have a number zero through nine in them, finally writing the text to filenames-with-numbers.txt. This is a contrived example but it illustrates something incredibly powerful about the command line: the text output of any command can easily be used as input for another command. While it may look like a lot of punctuated gibberish, it’s actually pretty intuitive to work with. Anyone who has tried copying GUI-formatted text into an environment with different formatting should be envious.

REPLs

So you want to play around with a programming language. You’ve written a file named “hello-world.py” or “hello-world.rb” or “hello-world.php” but you have no idea how to get the code to actually run. Command line to the rescue! If you have the programming language installed and in your path, you can run python hello-world.py or ruby hello-world.rb or php hello-world.php and the output of your script will print right in your terminal. But wait, there’s more!

Many modern scripting languages come with a REPL built-in, which stands for “Read-Eval-Print loop.” In English, this means you write text that’s instantly evaluated as code in the programing language. For instance, below I enter the Python REPL and do some simple math:

$ python
Python 2.7.2
Type "help", "copyright", "credits" or "license" for more information.
>>> 1 + 2
3
>>> 54 * 34
1836
>>> 64 % 3
1
>>> exit()

The $ represents my command prompt, so I simply ran the command python which entered the REPL, printing out some basic information like the version number of the language I’m using. Inside the REPL, I did some addition, multiplication, and a modulus. The exit() function call at the end exited the REPL and put me back in my command prompt. There’s really no better way to try out a programming language than with a REPL. [2] The REPL commands for Ruby and PHP are irb and php -a respectively.

Stumbling Blocks

Everyone who starts out working on the command line will run into a bunch of common hangups. It’s frustrating, but it doesn’t need to be. It’s really like learning common user interface conventions: how would you know an anachronistic floppy disk means “save this file” if you hadn’t already clicked it a million times? Below is my attempt to alleviate some of the most common quirks of the command line.

Where Is It?

Before we get too far, it would probably be good to know how to get to a command prompt in the first place. You use a terminal emulator to open a command prompt in a window on your operating system. On a Mac, the terminal emulator is the aptly-named Terminal.app, which is located in Applications\Utilities. On Ubuntu Linux, there’s also a Terminal application which you can find using the Dash or with the handy Ctrl+Alt+T shortcut. [3] KDE Linux distributions use Konsole as the default command line application instead. Finally, Windows has a couple terminal emulators and, sadly, they are incompatible with *NIX shells like those found on Mac and Linux machines. Windows PowerShell can be found in Start > All Programs > Accessories or by searching after clicking the Start button. You can open PowerShell on Windows 8 by searching as well.

Escaping Spaces

Spaces are a meaningful character on the command line: they separate one command from the next. So when you leave spaces in filenames or text strings, commands tend to return errors. You need to escape spaces in one of two ways: precede a space with a backslash, “\”, which tells the command line to interpret the following character literally (i.e. not as a directive), or by wrapping the string with spaces in quotes. So mv File Name.txt New Name.txt will be greeted with the usage information for the mv command because the program assumes you don’t understand how to use it, while mv "Sad Cats.txt" "LOL Cats.txt" will successfully rename “Sad Cats.txt” to “LOL Cats.txt”.

Luckily, you won’t need to type quotes or slashes very often due to the miracle that is tab completion. If you start typing a command or file name, you can hit the tab key and your shell will try to fill in the rest. If there are two names that begin identically then you’ll have to provide enough to disambiguate between the two: if “This is my file.txt” and “This is my second file.txt” are both in the same folder, you’ll have to type at least “This is my ” and then, depending on whether your next letter is an F or an S, the shell can tab complete whatever follows to the appropriate name.

Copy & Paste

Command line interfaces were invented before common GUI applications and their keyboard shortcuts like Ctrl+V and Ctrl+C. Those shortcuts were already assigned different actions on the command line and so they typically do not do what you’d expect, since for backwards compatibility they need to stick to their original meanings. So does that mean you have to type every long URL or string of text into the terminal? No! You can still copy-paste but it works a bit different on most terminals. On Ubuntu Linux, Ctrl+Shift+C or V will perform copy and paste respectively, while I’ve found that right-clicking in Windows PowerShell will paste. Mac OS X’s Terminal.app can actually use the conventional ⌘+C or ⌘+V because they don’t conflict with Ctrl.

Moving Around the Line

Too many times I’ve typed out a long command, perhaps one with a URL or other pasted string of text in it, only to spot a typo dozens of characters back. On the command line, you cannot simply click to move your cursor to a different position, you have to press the back arrow dozens of times to go back and correct a mistake.

Or so I thought. On Mac’s Terminal.app, option-click will move the cursor. Unfortunately, most other terminal applications don’t provide any mouse navigation. Luckily, there’s a series of keyboard shortcuts that work in many popular shells:

  • Ctrl+A jumps to the beginning of the line
  • Ctrl+E jumps to the end of the line
  • Ctrl+U deletes to beginning of line
  • Ctrl+K deletes to end of line
  • Ctrl+W deletes the word next to cursor

Those shortcuts can save you a lot time and are often quicker than using the mouse. Typing Ctrl+W to delete a lengthy URL is much more convenient than shift-clicking with the mouse to select it all, then hitting the delete key.

Make It Stop!!!

One of the first tips for learning the command line is to “read the friendly manual.” You can run the man command (short for manual) and pass it any other command to learn more about its usage, e.g. man cp will give you the manual of the copy command. However, the manual is often presented in a special format; it doesn’t just print the manual, it gives you a scrollable interface that replaces the command prompt. But how the heck do you exit the manual to get back to the command line? I’ll admit, when I was first learning, I used to simply close the terminal and re-open because I had no idea how to get out of the all-too-friendly manual.

But that’s unnecessary: pressing the letter q will quit the manual, while battering away on the ESC key or typing “exit please dear lord let me exit” won’t do a thing. q exits a few other commands, too.

Another good trick is Ctrl+C which causes a keyboard interrupt, canceling whatever process is running. I use this all the time because I frequently run a test server from the command line, or a SASS command that watches for file changes, or do something really stupid that will execute forever. Ctrl+C is always the exit strategy.

The PATH

So you installed the “awesomesauce” software, but every time you run awesomesauce in your command prompt you get a message like “command not found.” What gives?

All shells come with a PATH variable that specifies where the shell looks for executable programs. You can’t simply type the name of a script or executable anywhere on your system and expect the shell to know about it. Instead, you have to tell the command line where to look. Let’s say I just installed awesomesauce to ~/bin/awesomesauce where ~ stands for my user’s home folder (on Mac OS X this will be /Users/MyUsername, for example—you can run echo ~ to see where your home folder is). Here’s how I get it working:

$ # command isn't in my path yet - this is a comment by the way
$ awesomesauce
bash: awesomesauce: command not found
$ export PATH=$PATH:~/bin
$ awesomesauce
You executed the Awesome Sauce command! Congratulations!

The export command lets me modify my PATH variable, appending the ~/bin directory to the list of other places in the PATH. Now that the shell is looking in ~/bin, it sees the awesomesauce command and lets me run it from the command line.

It quickly gets tedious appending directories to your PATH every time you want to use something, so it’s wise to use a startup script that runs every time you open a new Terminal. In BASH, the common shell that comes with Mac OS X and is the default in most Linux distributions, you can do this by adding the appropriate export commands to a file named .bash_profile in your home file. The commands in .bash_profile are executed every time a new Terminal window is opened.

Use the Google, my Friend

There are certainly other hangups not covered above, but a tremendous amount of good information exists on the web. People have been using command line interfaces for quite a while now and there is documentation for almost everything. There are great question-and-answer forums, like StackExchange’s Superuser section, with tons of content on the command line and writing shell scripts. I’ve basically self-taught myself the command line using Google and a few select sources. In fact, the man command alone is one of the shining advantages of the command line: image if you could just type text like man spot healing brush in PhotoShop to figure out how all those crazy tools work?

Learning the command line is a challenge but it’s well worth the investment. Once you have a few basics under your belt, it opens up vast possibilities and can greatly increase your productivity. Still, I wouldn’t say that everyone needs to know the command line. Not everyone needs to learn coding either, but everyone can benefit from it. With a little practice, some trial and error, and many, many Google searches, you’ll be well on your way to commandeering like a boss.

Further Reading

wiki.bash-hackers.org – a great wiki for learning more about the common BASH shell

ss64.com – command line reference

Using the Terminal – Ubuntu’s guide to the command line

In the Beginning was the Command Line – Neal Stephenson’s treatise about the command line, GUIs, Windows, Linux, & BeOS. It actually isn’t that much about the command line but it’s an interesting read.

Footnotes

[1]^ The commands listed in this post will not work on Windows, but that doesn’t mean you can’t do the same things: the names and syntax of the commands are just different. It’s worth noting that Windows users can use the Cygwin project to get a shell experience comparable to *NIX systems.

[2]^ If you’re still too scared to try the command line after this post, the great repl.it site provides REPLs for over a dozen different programming languages.

[3]^ The default terminal on Ubuntu, and many other Linuxes, is technically “GNOME Terminal” but it may show up as just Terminal in search results. While these are the default terminals, most systems have more advanced alternatives that offer a few niceties like arranging terminal windows in a grid, paste history, and configurable keyboard shortcuts. On Mac, iTerm2 is an excellent choice. Lifehacker recommends Terminator for Linux, and it is also available for Windows and Mac. Wikipedia has an unnecessarily long list of terminal emulators for the truly insane.


Comments are closed.