The command line is the original and most powerful way of navigating and manipulating the file system. Many new programmers avoid the command line because it seems intimidating, confusing, and (ahem) nerdy. You can actually get pretty far without knowing anything about the command line, but eventually you will need it. You might as well learn it early on. You won’t be sorry you did.
Windows Explorer (not to be confused with Internet Explorer), Mac’s Finder, and Linux’s Nautilus and Konqueror are all graphical representations of the file system. They show directories as little folder icons, and files as little file icons. You can click directories to show their contents, and you can click files to open them with the default application. This interface makes the file system accessible to the average user, and it provides easy-to-use features for the most common file operations. If you want to rename a file, that’s slightly more difficult (and the answer is not to open the file and click Save As with the new name and then delete the old file, although that works, too). Moving a file to a different directory might not be straightforward. Deleting a file can be tricky (usually I just drag it to the trash can icon, but I can’t find the trash can icon—what do I do?). For most of the basics, the GUI (graphical user interface) works great, but some things it doesn’t do well, and some things it just can’t do at all.
When I worked as a financial auditor, one of my first assignments was to copy each of the hundreds of files from the previous year’s audit into a new folder and change the filenames to end with 2011
instead of 2010
.
I started the task using the GUI. Copying the files into a new directory would have been fairly easy. I could have just highlighted all the files, pressed Ctrl+C, opened the new directory, and pressed Ctrl+V. But there was a catch: I wanted to copy only the spreadsheet files whose names ended with 2010
. So I sorted the files by type, hoping the needed files would be grouped together, but of course, they weren’t. I ended up copying by 3s, 4s, and occasionally 20s instead of 100s. And that was still the easy part. When I had all the files in the new directory, I had to rename them. On Windows Explorer, clicking a file once highlights that file, and clicking a highlighted file allows you to rename that file. However, double-clicking a file opens that file. So I clicked on a file, waited for a moment, clicked again, then pressed the right arrow (to bring the cursor to the end of the filename), backspaced one time, then pressed 1, and repeated a few hundred times. For about one in five files, I didn’t wait long enough before the second click, Windows recognized my clicks as double-clicks, and then I had to wait as my woefully slow laptop (with not enough RAM) loaded the file in Excel; then I closed the file, went back to Windows Explorer, and started again. After about 10 minutes, I was ready to cry, quit, or both. I spent the next 30 minutes relearning how to write a Perl script to rename the files for me. I ran the script, and all the files were renamed in a fraction of a second.
Since then, I learned that I could have just used the command line for the whole thing, with just three simple commands (see Lisiting 3.1), two of which you will learn to use in the next section.
C:Userssfoote> cd audit2010
C:Userssfooteaudit2010> copy * ..2011*
C:Userssfooteaudit2010> cd ..2011
C:Userssfooteaudit2011> rename *_2010* *_2011*
The first command copies all files into the new directory named 2011
. The second command renames the files, replacing 2010
with 2011
for every file whose current filename ends with _2010
. Instead of spending an entire afternoon of mind-rotting manual work, I could have used the computer as it was meant to be used and finished the task in less than 30 seconds.
I think my biggest fear of the command line was the thought of having to memorize so many commands. Although I still think this is a valid fear, I have found that a small set of basic commands makes up about 80% of all the commands I use. Before we get into the commands, take a moment to understand the command line itself.
The first step is to open a terminal. If you already know how to do this, you can skip to the next section. On Linux, the terminal can be found in ApplicationSystem Tools. On Mac, Cmd+spacebar opens Spotlight (see Figure 3.5). From there, you can search for “Terminal.” On Windows, press StartRun, type cmd, and press Enter (see Figure 3.6).
When you open the terminal (or command prompt), you will see very little—no shiny buttons to click on. You just see a somewhat cryptic-looking line. Fear is usually just a lack of understanding, so let’s demystify that line in Listing 3.2.
sfoote@sfoote-mac:~ $
This line has four different components: username, computer name, file system location, and mode.
1. Username: sfoote
is my username. That’s the name I use when I log in.
2. Computer name: sfoote-macbook
is my computer’s name. This is one of the ways other computers on your network can find your computer.
3. File system location: ~
is your home directory. That’s where you start when you open the terminal. This is probably the most useful item in the line.
4. Mode: $
indicates that you are in the normal mode, with normal permissions. Don’t worry too much about this one.
Windows gives you only the file system location (see Listing 3.3), which, again, is the most useful. Windows also gives you the full path, whereas UNIX gives you only the current directory (although you can modify this).
C:Userssfoote>
Now on to the commands. The best way to learn these is to actually use them. So if you’re not already in front of a computer, now is the time. As we go through these examples, try running each of them on your own. You don’t need to type the #
or anything that comes after it; those are just comments to help you understand what is going on with each command.
In your prompt, you have the name of your current directory, but you don’t have the full path to the current directory. For instance, if my prompt says sfoote@sfoote-mac:js $
, I know that I’m in a directory called js
, but I might have multiple directories called js
. pwd
(for present working directory) gives me the full path to the current directory. Windows already gives you the full path, so you don’t need a pwd
command. See Listing 3.4.
sfoote@sfoote-mac:js $ pwd
/Users/sfoote/projects/website/static/js
When you first start your command prompt, you will likely be in your home directory. For the following exercises, you will want to be in the kittenbook
directory. But how can you get there?
Absolute and Relative Paths
When navigating the file system using the command line, you can specify the location of a file or directory in two ways. These are known as an absolute (full) path and a relative (partial) path. The full path always starts at the same place (the root directory), whereas the relative path is relative to the present working directory. Listings 3.5–3.10 should make this more clear.
sfoote@sfoote-mac:~ $ cd projects # Move into the projects directory,
sfoote@sfoote-mac:projects $ pwd # Now run pwd to see where we are
/Users/sfoote/projects
sfoote@sfoote-mac:projects $ cd kittenbook/js # Move into kittenbook/js directory
/Users/sfoote/projects/kittenbook/js
sfoote@sfoote-mac:js $ cd .. # Move up one directory.
sfoote@sfoote-mac:kittenbook $ pwd
/Users/sfoote/projects/kittenbook
sfoote@sfoote-mac:kittenbook $ cd ~ # Move to the home directory.
# The ~ will always take you home.
# It's like clicking your heels.
# Works in Linux and Mac only.
sfoote@sfoote-mac:~ $
sfoote@sfoote-mac:~ $ cd - # Move back to the directory that we just
# came from. We were in the kittenbook direct-
# ory, so we'll go back there.
# Works in Linux and Mac only.
sfoote@sfoote-mac:kittenbook $
sfoote@sfoote-mac:kittenbook $ cd js # move into the js directory
sfoote@sfoote-mac:js $ cd ../../puppybook # Move up 2 directories
# (../..), then from there
# to the puppybook directory.
# You will need to create (mkdir) the
# puppybook directory for this to work
sfoote@sfoote-mac:puppybook $ pwd
/Users/sfoote/projects/puppybook
sfoote@sfoote-mac:puppybook $ cd /Users/sfoote/projects/kittenbook/js
sfoote@sfoote-mac:js $ pwd
/Users/sfoote/projects/kittenbook/js
sfoote@sfoote-mac:js $ cd ~/projects/kittenbook # Use the home directory
# as our starting point
sfoote@sfoote-mac:kittenbook $ pwd
/Users/sfoote/projects/kittenbook
Note
When you are writing out paths on the command line, try pressing Tab (you might need to press it twice on Linux and Mac) to autocomplete what you’re typing or see a list of options.
When I’m using a GUI file browser, I can see all the files and directories inside the current directory. You can use ls
(or dir
on Windows) to show that same list on the command prompt. This command is often used along with cd
to help with navigation. See Listing 3.11.
sfoote@sfoote-mac:kittenbook $ ls
js manifest.json kittenbook.html
sfoote@sfoote-mac:kittenbook $ ls -a # List all files and directories
# (including hidden files)
# You probably won't see .git. I will
# explain what Git is in chapter 15.
. .. .git js manfiest.json kittenbook.html
sfoote@sfoote-mac:kittenbook $ ls js # List all the files and directories
# in the js directory (you can use
# any path, relative or full, and
# this will work)
prompt.js values.js
Did you notice the -a
in the second command? This is the first time you have seen a flag on a command. Flags modify the way the command works. Sometimes you add some text after the flag to further customize how the command works. You will see many more flags later.
Copying files and directories is really easy on the command line (see Listing 3.12).
sfoote@sfoote-mac:kittenbook $ cd js
sfoote@sfoote-mac:js $ cp prompt.js new_prompt.js
The cp
command takes two arguments. The first is the path (full or relative) to the file you want to copy, and the second is the path to where you want the new file to be. The path in the second argument can include a filename if you want to rename the file as you copy it. Be careful; if the new file already exists, running cp
overwrites the contents of that file without asking. Listing 3.12 shows the prompt.js
file being copied to a new file called new_prompt.js
.
In Listing 3.13, I have copied the entire js
directory into js_copy
. This shows that I can copy entire directories and that I can change the name of the new directory while I copy. The -r
flag (for recursive) is necessary to copy a directory.
sfoote@sfoote-mac:js $ cd ..
sfoote@sfoote-mac:kittenbook $ cp -r js/ js_copy
sfoote@sfoote-mac:kittenbook $ ls
js js_copy manifest.json kittenbook.html
The mv
command works a lot like cp
, except that it also deletes the original file (see Listing 3.14).
sfoote@sfoote-mac:kittenbook $ mv kittenbook.html js/ # Move kittenbook.html
# into the js directory
sfoote@sfoote-mac:kittenbook $ ls
js js_copy manifest.json
sfoote@sfoote-mac:kittenbook $ mv js/kittenbook.html . # Move kittenbook.html back
You can use mv
for moving files, and you can also use it for renaming files (see Listing 3.15).
sfoote@sfoote-mac:kittenbook $ cd js
sfoote@sfoote-mac:js $ mv new_prompt.js prompt_copy.js
sfoote@sfoote-mac:js $ ls
prompt.js prompt_copy.js kittenbook.html values.js
Computer programmers don’t like to type more than they have to, so the command to delete a file is rm
, which is short for remove. The Windows name (del
) is a bit easier to decode. This command deletes a file or directory (see Listing 3.16 and Listing 3.17, respectively). Use this command with caution, though, because there is no Undo button.
sfoote@sfoote-mac:js $ rm prompt_copy.js # Delete prompt_copy.js
sfoote@sfoote-mac:js $ ls
prompt.js kittenbook.html values.js
sfoote@sfoote-mac:js $ cd ..
sfoote@sfoote-mac:kittenbook $ rm js_copy # Delete the js_copy directory.
# It won't work because js_copy is
# a directory.
rm: js_copy/: is a directory
sfoote@sfoote-mac:kittenbook $ rm -rf js_copy # Try again, adding 2 flags.
# 'r' means recursive; delete this directory and any directories inside
# this directory. 'f' means force; don't ask questions, just delete.
If you can delete directories, you have to be able to create them, too. mkdir
creates a new directory with the given path. If you haven’t actually been following along up to this point, you really need to now because we’re going to start making changes that are important to how the kittenbook extension works. Listings 3.18 and 3.19 show how to create a new release
directory using the command line.
sfoote@sfoote-mac:kittenbook $ mkdir release # create release directory
sfoote@sfoote-mac:kittenbook $ ls
js manifest.json release
C:Userssfooteprojectskittenbook> md release
C:Userssfooteprojectskittenbook> dir
Directory of C:Userssfooteprojectskittenbook
04/24/2014 01:27 PM <DIR> js
04/24/2014 01:27 PM 324 manifest.json
04/24/2014 01:27 PM <DIR> release
1 File(s) 324 bytes
2 Dir(s) XXX bytes free
On Linux and Mac, cat
is often used to concatenate files, but you also can use it to quickly view the contents of a single file. cat
sends its output wherever you tell it to. If you don’t tell it where, the output is printed to the screen. Nearly all command-line commands treat their output in this way. In fact, this is called “standard out,” or STDOUT. The great thing is that you can take this output and put it wherever you want. You can use the output as the input of another command, or you can write the output to a file.
First, let’s see the output of two files using cat
in Listing 3.20.
sfoote@sfoote-mac:kittenbook $ cd js
sfoote@sfoote-mac:js $ cat values.js prompt.js
var projectName = 'kittenbook';
var versionNumber = '0.0.1';
var currentDate = new Date(); // Create Date object. More about objects and
// Date objects in chapter 5. This object will
// be used to build our date.
// currentTime will look like '2014-01-25 at 14:45:12'
var currentTime = currentDate.getFullYear() + '-' + // Set year
currentDate.getMonth() + '-' + // Set month
currentDate.getDate() + ' at ' + // Set day of the month
currentDate.getHours() + ':' + // Set hours (military time)
currentDate.getMinutes() + ':' + // Set minutes
currentDate.getSeconds(); // Set seconds
var userName = prompt('Hello, what's your name?'),
document.body.innerHTML = '<h1>Hello, ' + userName + '!</h1>' +
'<p>' + projectName + ' ' + versionNumber +
' accessed on: ' + currentTime + '</p>';
Now let’s redirect the output to a new file named main.js
. Let’s also put this new file in the release
directory we just created. The way to redirect output to a file is by using a greater-than symbol (>
) between the command and the name of the file where the output should go (see Listing 3.21). If the output file doesn’t already exist, it will be created. Use caution, though, because if the file does already exist, its current contents will be completely overwritten by the output of the command—again, there is no Undo button.
sfoote@sfoote-mac:js $ cat values.js prompt.js > ../release/main.js
sfoote@sfoote-mac:js $ cat ../release/main.js
var projectName = 'kittenbook';
var versionNumber = '0.0.1';
var currentDate = new Date(); // Create Date object. More about objects and
// Date objects in chapter 5. This object will
// be used to build our date.
// currentTime will look like '2014-01-25 at 14:45:12'
var currentTime = currentDate.getFullYear() + '-' + // Set year
(currentDate.getMonth() + 1) + '-' + // Set month
currentDate.getDate() + ' at ' + // Set day of the month
currentDate.getHours() + ':' + // Set hours (military time)
currentDate.getMinutes() + ':' + // Set minutes
currentDate.getSeconds(); // Set seconds
var userName = prompt('Hello, what's your name?'),
document.body.innerHTML = '<h1>Hello, ' + userName + '!</h1>' +
'<p>' + projectName + ' ' + versionNumber +
' accessed on: ' + currentTime + '</p>';
On Windows, either type
or copy
can do the job of concatenating files (see Listing 3.22).
C:Userssfooteprojectskittenbook> type values.js prompt.js > ..
eleasemain.js
C:Userssfooteprojectskittenbook> copy /b values.js+prompt.js ..
eleasemain.js
If you need to find a file that contains some specific text, grep
is the command for you. grep
can search for specific text, such as Steven
, and it can also search for patterns, as with 20XX
(for 2000
, 2001
, 2002
, and so on). See Listing 3.23.
sfoote@sfoote-mac:js $ cd ..
sfoote@sfoote-mac:kittenbook $ grep –r "kittenbook" * # Search for the text
# "kittenbook" in all files
# in the project directory
js/kittenbook.html: <script type="text/javascript" src="kittenbook.js"></script>
js/values.js:var projectName = 'kittenbook';
manifest.json: "name": "kittenbook",
Again, the best way to learn these commands is to practice them. As you start, it might be useful to open a command prompt and a graphical file explorer together so that you can see how what happens in one affects the other. Before long, you will see how much faster the command line can be.
18.217.5.86