Here are a few simple but very effective tips that will make you lightning fast on the command line.
I remember the first time a friend of mine introduced me to Linux and showed me how I didn't need to type commands and path names fully—I could just start typing and use the Tab key to complete the rest. That was so cool. I think everybody loves Tab completion because it's something you use pretty much every minute you spend in the shell. Over time, I discovered many more shortcuts and time-saving tricks, many of which I have come to use almost as frequently as Tab completion.
In this article, I highlight a set of tricks for common situations that make a huge difference for me:
Working in screen sessions: core features that will get you a long way.
Editing the command line: moving around quickly and editing quickly.
Viewing files or man pages using less.
E-mailing yourself relevant log snippets or alerts triggered by events.
While reading the article, it would be best to have a terminal window open so you can try using the tips right away. All the tips should work in Linux, UNIX and similar systems without any configuration.
Screen has been covered in Linux Journal before (see Resources), but to put it simply, screen lets you have multiple “windows” within a single terminal application. The best part is that you can detach and reattach to a running screen session at any time, so you can continue your previous work exactly where you left off. This is most useful when working on a remote server.
Luckily, you really don't need to master screen to benefit from it greatly. You already can enjoy its most useful benefits by using just a few key features, namely the following:
screen -R projectx: reattach to the screen session named “projectx” or create it fresh now.
Ctrl-a c: create a new window.
Ctrl-a n: switch to the next window.
Ctrl-a p: switch to the previous window.
Ctrl-a 0: switch to the first window; use Ctrl-a 1 for the second window, and so on.
Ctrl-a w: view the list of windows.
Ctrl-a d: detach from this screen session.
screen -ls: view the list of screen sessions.
Note: in the above list, “Ctrl-a c” means pressing the Ctrl and a keys at the same time, followed by c. Ctrl-a is called the command key, and all screen commands start with this key sequence.
Let me show all of these in the context of a realistic example: debugging a Django Web site on my remote hosting server, which usually involves the following activities:
Editing the configuration file.
Running some commands (performing Django operations).
Restarting the Web site.
Viewing the Web site logs.
Of course, I could do all these things one by one, but it's a lot more practical to have multiple windows open for each. I could use multiple real terminal windows, but reopening them every time I need to do this kind of work would be tedious and slow. Screen can make this much faster and easier.
Starting Screen:
Before you start screen, it's good to navigate to the directory where you expect to do most of your work first. This is because new windows within screen will all start in that directory. In my example, I first navigate to my Django project's directory, so that when I open new screen windows, the relevant files will be right there in front of me.
There are different ways of starting screen, but I recommend this one:
screen -R mysite
When you run this the first time, it creates a screen session named “mysite”. Later you can use this same command to reconnect to this session again. (The -R flag stands for reattach.)
Creating Windows:
Now that I'm in screen, let's say I start editing the configuration of the Django Web site:
vim mysite/settings.py
Let's say I made some changes, and now I want to restart the site. I could exit vim or put it in the background in order to run the command to restart the site, but I anticipate I will need to make further changes right here. It's easier just to create a new window now, using the screen command Ctrl-a c.
It's easy to create another window every time you start doing something different from your current activity. This is especially useful when you need to change the directory between commands. For example, if you have script files in /some/long/path/scripts and log files in /other/long/path/logs, then instead of jumping between directories, just keep a separate window for each.
In this example, first I started looking at the configuration files. Next, I wanted to restart the Web site. Then I wanted to run some Django commands, and then I wanted to look at the logs. All these are activities I tend to do many times per debugging session, so it makes sense to create a separate window for each activity.
The cost of creating a new window is so small, you can do it without thinking. Don't interrupt your current activity; fire up another window with Ctrl-a c and rock on.
Switching between Windows:
The windows you create in screen are numbered starting from zero. You can switch to a window by its number—for example, jump to the first window with Ctrl-a 0, the second window with Ctrl-a 1 and so on. It's also very convenient to switch to the next and previous windows with Ctrl-a n and Ctrl-a p, respectively.
Listing Your Windows:
If you're starting to lose track of which window you are in, check the list of windows with Ctrl-a w or Ctrl-a ". The former shows the list of windows in the status line (at the bottom) of the screen, showing the current window marked with a *. The latter shows the list of windows in a more user-friendly format as a menu.
Detaching from and Reattaching to a Session:
The best time-saving feature of screen is reattaching to existing sessions. You can detach cleanly from the current screen session with Ctrl-a d. But you don't really need to. You could just as well simply close the terminal window.
The great thing about screen sessions is that whatever way you disconnected from them, you can reattach later. At the end of the day, you can shut down your local PC without closing a remote screen session and come back to it the next day by running the same command you used to start it, as in this example with screen -R mysite.
You might have multiple screen sessions running for different purposes. You can list them all with:
screen -ls
If you are disconnected from screen abruptly, sometimes it may think you are still in an attached state, which will prevent you from reattaching with the usual command screen -R label. In that case, you can append a -D flag to force detach from any existing connections—for example:
screen -R label -D
Learning More about Screen:
If you want to learn more, see the man page and the links in the Resources section. The built-in cheat sheet of shortcuts also comes handy, and you can view it with Ctrl-a ?.
I also should mention one of screen's competitor: tmux. I chose screen in this article because in my experience, it is more available in systems I cannot control. You can do everything I covered above with tmux as well. Use whichever is available in the remote system in which you find yourself.
Finally, you can get the most out of screen when working on a remote system—for example, over an SSH session. When working locally, it's probably more practical to use a terminal application with tabs. That's not exactly the same thing, but probably close enough.
Many highly practical shortcuts can make you faster and more efficient on the command line in different ways:
Find and re-run or edit a long and complex command from the history.
Edit much more quickly than just using the backspace key and retyping text.
Move around much faster than just using the left- and right-arrow keys.
Finding a Command in the History:
If you want to repeat a command you executed recently, it may be easy enough just to press the up-arrow key a few times until you find it. If the command was more than only a few steps ago though, this becomes unwieldy. Very often, it's much more practical to use the Ctrl-r shortcut instead to find a specific command by a fragment.
To search for a command in the past, press Ctrl-r and start typing any fragment you remember from it. As you type, the most recent matching line will appear on the command line. This is an incremental search, which means you can keep typing or deleting letters, and the matched command will change dynamically.
Let's try this with an example. Say I ran these commands yesterday, which means they are still in my recent history but too far away simply to use the up arrow:
... cd ~/dev/git/github/bashoneliners/ . ~/virtualenv/bashoneliners/bin/activate ./run.sh pip install --upgrade django git push beta master:beta git push release master:release git status ...
Let's say I want to activate the virtualenv again. That's a hassle to type again, because I have to type at least a few characters at each path segment, even with Tab completion. Instead, it's a lot easier to press Ctrl-r and start typing “activate”.
For a slightly more complex example, let's say I want to run a git push command again, but I don't remember exactly which one. So I press Ctrl-r and start typing “push”. This will match the most recent command, but I actually want the one before that, and I don't remember a better fragment to type. The solution is to press Ctrl-r again, in the middle of my current search, as that jumps to the next matching command.
This is really extremely useful, saving not only the time of typing, but also often the time of thinking too. Imagine one of those long one-liners where you processed a text file through a long sequence of pipes with sed, awk, Perl and whatnot; or an rsync command with many flags, filters and exclusions; or complex loops using “for” and “while”. You can bring those back to your command line quickly using Ctrl-r and some fragment you remember from them.
Here are a few other things to note:
The search is case-sensitive.
You can abort the search with Ctrl-c.
To edit the line before running it, press any of the arrow keys.
This trick can be even more useful if you pick up some new habits. For example, when referring to a path you use often, type the absolute path rather than a relative path. That way, the command will be reusable later from any directory.
Moving Around Quickly and Editing Quickly:
Basic editing on the command line involves moving around with the arrow keys and deleting characters with Backspace or Delete. When there are more than only a few characters to move or delete, using these basic keys is just too slow. You can do the same much faster by knowing just a handful of interesting shortcuts:
Ctrl-w: cut text backward until space.
Esc-Backspace: cut one word backward.
Esc-Delete: cut one word forward.
Ctrl-k: cut from current position until the end of the line.
Ctrl-y: paste the most recently cut text.
Not only is it faster to delete portions of a line chunk by chunk like this, but an added bonus is that text deleted this way is saved in a register so that you can paste it later if needed. Take, for example, the following sequence of commands:
git init --bare /path/to/repo.git git remote add origin /path/to/repo.git
Notice that the second command uses the same path at the end. Instead of typing that path twice, you could copy and paste it from the first command, using this sequence of keystrokes:
Press the up arrow to bring back the previous command.
Press Ctrl-w to cut the path part: “/path/to/repo.git”.
Press Ctrl-c to cancel the current command.
Type git remote add origin, and press Ctrl-y to paste the path.
Some of the editing shortcuts are more useful in combination with moving shortcuts:
Ctrl-a: jump to the beginning of the line.
Ctrl-e: jump to the end of the line.
Esc-b: jump one word backward.
Esc-f: jump one word forward.
Jumping to the beginning is very useful if you mistype the first words of a long command. You can jump to the beginning much faster than with the left-arrow key.
Jumping forward and backward is very practical when editing the middle part of a long command, such as the middle of long path segments.
Putting It All Together:
A good starting point for learning these little tricks is to stop some old inefficient habits:
Don't clear the command line with the Backspace key. Use Ctrl-c instead.
Don't delete long arguments with the Backspace key. Use Ctrl-w instead.
Don't move to the beginning or the end of the line using the left- and right-arrow keys. Jump with Ctrl-a and Ctrl-e instead.
Don't move over long terms using the arrow keys. Jump over terms with Esc-b and Esc-f instead.
Don't press the up arrow 20 times to find a not-so-recent previous command. Jump to it directly with Ctrl-r instead.
Don't type anything twice on the same line. Copy it once with Ctrl-w, and reuse it many times with Ctrl-y instead.
Once you get the hang of it, you will start to see more and more situations where you can combine these shortcuts in interesting ways and minimize your typing.
Learning More about Command-Line Editing:
If you want to learn more, see the bash man page and search for “READLINE”, “Commands for Moving” and “Commands for Changing Text”.
The less command is a very handy tool for viewing files, and it's the default application for viewing man pages in many modern systems. It has many highly practical shortcuts that can make you faster and more efficient in different ways:
Searching forward and backward.
Moving around quickly.
Placing markers and jumping to markers.
Searching Forward and Backward:
You can search forward for some text by typing / followed by the pattern to search for. To search backward, use ? instead of /. The search pattern can be a basic regular expression. If your terminal supports it, the search results are highlighted with inverted foreground and background colors.
You can jump to the next result by pressing n, and to the previous result by pressing N. The direction of next and previous is relative to the direction of the search itself. That is, when searching forward with /, pressing n will move you forward in the file, and when searching backward with ?, pressing n will move you backward in the file.
If you use the vim editor, you should feel right at home, as these shortcuts work the same way as in vim.
Searching is case-sensitive by default, unless you specify the -i flag when starting less. When reading a file, you can toggle between case-sensitive and insensitive modes by typing -i.
Moving Around Quickly:
Here are a couple shortcuts to help you move around quickly:
g: jump to the beginning of the file.
G: jump to the end of the file.
space: move forward by one window.
b: move backward by one window.
d: move down by a half-window.
u: move up by a half-window.
Using Markers:
Markers are extremely useful in situations when you need to jump between two or more different parts within the same file repeatedly.
For example, let's say you are viewing a server log with initialization information near the beginning of the file and some errors somewhere in the middle. You need to switch between the two parts while trying to figure out what's going on, but using search repeatedly to find the relevant parts is very inconvenient.
A good solution is to place markers at the two locations so you can jump to them directly. Markers work similarly as in the vim editor: you can mark the current position by pressing m followed by a lowercase letter, and you can jump to a marker by pressing ' followed by the same letter. In this example, I would mark the initialization part with mi and the part with the error with me, so that I could jump to them easily with 'i and 'e. I chose the letters as the initials of what the locations represent, so I can remember them easily.
Learning More Shortcuts:
If you are interested in more, see the man page for the less command. The built-in cheat sheet of shortcuts also comes handy, and you can view it by pressing h.
When working on a remote server, getting data back to your PC can be inconvenient sometimes—for example, when your PC is NAT-ed and the server cannot connect to it directly with rsync or scp. A quick alternative might be sending data by e-mail instead.
Another good scenario for e-mailing yourself is to use alerts triggered by something you were waiting for, such as a crashed server coming back on-line or other particular system events.
E-mailing a Log Snippet:
Let's say you found the log of errors crashing your remote service, and you would like to copy it to your PC quickly. Let's further assume the relevant log spans multiple pages, so it would be inconvenient to copy and paste from the terminal window. Let's say you can extract the relevant part using a combination of the head, tail and grep commands. You could save the log snippet in a file and run rsync on your local PC to copy it, or you could just mail it to yourself by simply piping it to this command:
mailx -s 'error logs' me@example.com
Depending on your system, the mailx command might be different, but the parameters are probably the same: -s specifies the subject (optional), the remaining arguments are the destination e-mail addresses, and the standard input is used as the message body.
Triggering an E-mail Alert after a Long Task
When you run a long task, such as copying a large file, it can be annoying to wait and keep checking whether it has finished. It's better to arrange to trigger an e-mail to yourself when the copying is complete—for example:
the_long_task; date | mailx -s 'job done' me@example.com
That is, when the long task has completed, the e-mail command will run. In this example, the message body simply will be the output of the date command. In a real situation, you probably will want to use something more interesting and relevant as the message—for example ls -lh on the file that was copied or even multiple commands grouped together like this:
the_long_task; { df -h; tail some.log; } | \ mailx -s 'job done' me@example.com
Triggering an E-mail Alert by Any Kind of Event:
Have you ever been in one of the following situations?
You are waiting for crashed serverX to come back on-line.
You are tailing a server log, waiting for a user to test your new evolution, which will trigger a particular entry in the log.
You are waiting for another team to deploy an updated .jar file.
Instead of staring at the screen or checking repeatedly whether the event you are waiting for has happened, you could use this kind of one-liner:
while :; do date; CONDITION && break; sleep 300; \ done; MAILME
This is essentially an infinite loop, with an appropriate CONDITION in the middle to exit the loop and, thus, trigger the e-mail command. Inside the loop, I print the date, just so that I can see the loop is alive, and sleep for five minutes (300 seconds) in each cycle to avoid overloading the machine I'm on.
CONDITION can be any shell command, and its exit code will determine whether the loop should exit. For the situations outlined above, you could write the CONDITION like this:
ping -c1 serverX: emit a single ping to serverX. If it responds, ping will exit with success, ending the loop.
grep pattern /path/to/log: search for the expected pattern in the log. If the pattern is found, grep will exit with success, ending the loop.
find /path/to/jar -newer /path/to/jar.marker: this assumes that before starting the infinite loop, you created a marker file like this: touch -r /path/to/jar /path/to/jar.marker in order to save a copy of the exact same timestamp as the .jar file you want to monitor. The find command will exit with success after the jar file has been updated.
In short, don't wait for a long-running task or some external event. Set up an infinite loop, and alert yourself by e-mail when there is something interesting to see.
All the tips in this article are standard features and should work in on Linux, UNIX and similar systems. I have barely scratched the surface here, highlighting the minimal set of features in each area that should provide the biggest bang for your buck. Once you get used to using them, these little tricks will make you a real ninja in the shell, jumping around and getting things done lightning fast with minimal typing.