Getting to Grips with Bash

an introduction to the *nix command line

by Mike Peters, September 2003

Many users new to Linux are intimidated by the very thought of having to do something from a command prompt or console. Experienced users who suggest a Newbie should fire up their console to fix a problem are seen as geeks who sit in front of black screens all day memorizing arcane commands and symbols. However, the truth of the matter is that many times a job can be accomplished much quicker by knowing the right command or sequence of commands. Nobody, especially programmers and admins, wants to sit around all day trying to remember and type out long series of commands. Many shortcuts have been incorporated into Bash which allow the user to edit and execute commands quickly and efficiently and make a GUI seem clumsy and unresponsive in comparison.

This article is meant as an introduction to the many shortcuts and tricks which remain hidden to many novice users, many intermediate users may also find examples of things they've missed here too. This is by no means a comprehensive list to the features of Bash, the man pages are there for that, rather I outline the most commonly used and useful tricks used at a command prompt. Finally, although I refer specifically to Bash, much of what is here is relevant to other shells too.

TAB Completion

The best known of Bash's labour saving features is that of command line completion. This is the ability of Bash to complete long commands or names when you hit the TAB key. For example, let's say you have a directory called /home/mike/projects/foo and you want to list the files in that directory. Rather than typing the whole command, ls /home/mike/projects/foo, out you would just type something like:

ls /h TAB m TAB p TAB f TAB Enter

When you type the first letter of a word or command, pressing TAB automatically completes that word. So:

ls /h TAB

is automatically completed to ls /home/ by the shell. If there is more than one name or command starting with that letter the bell rings and you must add the second letter and so on until you have a unique sequence which the shell can complete. Hitting TAB twice will show the possible completions. So, for example if we have a home directory containing folders for mike, martin and michelle:

ls /home/m TAB

will not complete,

ls /home/m TAB TAB

will show:

martin
michelle
mike

as possible completions. Whilst

ls /home/mi TAB TAB

will show:

michelle
mike

as possible completions. Finally:

ls /home/mic TAB

will expand to ls /home/michelle.

This feature not only saves time and effort, but it can also help you to find commands and files when you can't quite remember the name. Oh, what was that command called again? It started with a c, I'm sure. Well, just type c and hit TAB TAB. You'll get a list of commands starting with c. The same goes when you're hunting for files or directories.

Most new users to Linux never get beyond command line completion. However, useful as it is, it is not the be all and end all of Bash's features for workshy users.

Navigating and Editing the Command Line

We all know that we can use the right and left cursor keys to move back and forth across the command line. Most of us know also that the Home and End keys will take the cursor to the start and end of a line respectively. But what if they don't work (and they often don't). Well these keys should have your cursor hopping merrily back and forth:

Ctrl-a Move to the start of the line.
Ctrl-e Move to the end of the line.
Ctrl-b Move back one character.
Alt-b Move back one word.
Ctrl-f Move forward one character.
Alt-f Move forward one word.
Alt-] x Where x is any character, moves the cursor forward to the next occurance of x.
Alt-Ctrl-] x Where x is any character, moves the cursor backwards to the previous occurance of x.
Ctrl-u Delete from the cursor to the beginning of the line.
Ctrl-k Delete from the cursor to the end of the line.
Ctrl-w Delete from the cursor to the start of the word.
Esc-Del Delete previous word (may not work, instead try Esc followed by Backspace)
Ctrl-y Pastes text from the clipboard.
Ctrl-l Clear the screen leaving the current line at the top of the screen.
Ctrl-x Ctrl-u Undo the last changes. Ctrl-_ does the same
Alt-r Undo all changes to the line.

A word of warning, don't, whatever you do, press Ctrl-s.*

A quick reference chart to the shortcuts covered in this article is available here (opens a new window).

The Benefits of Knowing Your History

Much of the power of Bash comes from it's history and the many short cuts for accessing the commands stored there. Type:

history

What you should see is a list of commands which you have executed up till now in this session. eg a random excert from my bash history shows:

197 ssh 192.168.20.1 ls /home/mike/mp3s/ | wc -l
198 find /usr/ -iname libperl.so
199 find /home/comp_farm/ -iname libperl.so
200 su
201 cd /home/comp_farm/
202 ls macs-0.7-alpha/*.xml
203 cd macs-0.7-alpha/
204 cat /usr/local/macs/etc/macs/config.xml >config.xml
205 tar -xzvf ../sources/libwww-perl-5.64.tar.gz
206 cd libwww-perl-5.64/
207 perl Makefile.PL
208 perl -MCPAN -e 'install HTML::HeadParser'

It's nice to have a list of the commands which we've executed, but, it would be even nicer if we had an easy way to reaccess those commands and that's just what Bash provides. You can see and access the last command you executed by hitting the up arrow, keep hitting up to access commands furrther up the list. You can move back down the list by hitting the down arrow. As with the navigation keys above there are other key sequences assigned to navigate the history in the case that the cursor keys don't work, namely Ctrl-p for up (previous) and Ctrl-n for down (next). Alt-< Takes you to the beginning of your history and Alt-> to the end.

Although it may be fairly useful to be able to hunt through your command history like this, it's not really that special. Much more useful is the ability to search the history. Press:

Ctrl-r

and you'll see a prompt which looks like:

(reverse-i-search)`':

Start typing and to the right of the colon you'll see the last command you executed which contains what you type. Try it by typing cd. Hitting enter executes the command for you or you can hit escape and the command is placed at the prompt so that you can edit it.

Alt-p

Does the same but initiates a non-incremental search.

If you want to execute the last command again you can do this by pressing the up arrow and enter. There is another way of doing this however:

!!

You may ask what the point of this is, afterall, surely it's easier just to press up and enter and I'd agree, most of the time. There are occasions though when it's useful. Let's say you try to execute a file, for example /home/downloads/r1p1_linux22_libc6_i386_a1.bin, but it doesn't work because the file isn't executable, first you need to chmod the file and then execute it, so, the relatively long way would be:

Wed Sep 03.:mike@home:. mike $:> /home/downloads/r1p1_linux22_libc6_i386_a1.bin
-bash: /home/downloads/r1p1_linux22_libc6_i386_a1.bin: Permission denied

Wed Sep 03.:mike@home:. mike $:> chmod +x /home/downloads/r1p1_linux22_libc6_i386_a1.bin

Now you press up twice and enter to execute the file again. Alternatively, you could have done:

Wed Sep 03.:mike@home:. mike $:> /home/downloads/r1p1_linux22_libc6_i386_a1.bin
-bash: /home/downloads/r1p1_linux22_libc6_i386_a1.bin: Permission denied

Wed Sep 03.:mike@home:. mike $:> chmod +x /home/downloads/r1p1_linux22_libc6_i386_a1.bin; !!

and the file would be exected for you as, when you typed the command, the last command in history was /home/downloads/r1p1_linux22_libc6_i386_a1.bin. We could actually make this comand even shorter using !$. !$ expands to the last argument of the last command executed and so in this case would also be /home/downloads/r1p1_linux22_libc6_i386_a1.bin. In the above example we could replace

Wed Sep 03.:mike@home:. mike $:> chmod +x /home/downloads/r1p1_linux22_libc6_i386_a1.bin; !!

with

Wed Sep 03.:mike@home:. mike $:> chmod +x !$; !!

Another example using !$ is when you open a file with less for reading but then realise you want to edit it:

less /home/scripts/check_links.pl
vi !$

I can also execute the file now with just:

!$

But, what if I execute another command before I try to execute the file, now !$ won't work! Imagine:

less /home/scripts/check_links.pl
vi !$
cd /home/httpd/html
!$

Fails with:

Wed Sep 03.:mike@home:. html $:> !$
/home/httpd/html/
-bash: /home/httpd/html/: is a directory

In place of !$ I should have done Alt-.. (ie hold down Alt and full stop twice). Alt and full stop cycles back through the last argument of commands in turn and prints to the prompt. !^ can be used to refer to the first argument in the previous command.

There are a couple of other shortcuts using ! which you may find useful. !abc expands to the last command in history beginning with abc, enter executes the command, so:

!cd Enter

will execute the last command you executed begining with cd. !abc:p expands to the last command in history beginning with abc, however in this case enter prints the command that would be executed and places it as the last comand in history, you can then execute it if you want to with up and enter or !!.

!n, where n is a number executes the command in history which corresponds to n. For example, from the history example above:

!199

would expand to find /home/comp_farm/ -iname libperl.so.

If you are ever unsure what a shortcut will expand to, you can find out easily with Alt-Ctrl-e.

Another really useful tool is ^xyz^abc. This will replace the first occurance of xyz in the preceding command with abc. I use it often for things like correcting a spelling mistake or for changing the options in a command. For example if I do:

ls -l /var/www/htdocs/admin/

and then decide that I wanted to list hidden files too, I could do:

^-l^-la

A quick reference chart to the shortcuts covered in this article is available here (opens a new window).

Aliases

Many of us use certain commands over and over again, or we have preferred combinations of options which we always give to certain commands. We can create shortcuts to these commands by giving them an alias in our ~/.bashrc file. The format is:

alias new_name='command -options'

Some example aliases are:

alias ls='ls --color -CF'
alias rmkpid='rm /home/mike/.kde/share/apps/kppp/kppp.pid'
alias greps='ps -aux | grep $1'

Emacs or Vi

Anyone who has spent any time using emacs will have noticed that the keybindings I've listed are the same as in emacs. If you've never used emacs before though, and you learn the above keybindings, you've just had your first lesson in emacs without even knowing it. If you prefer vi however you may wish to use vi keybindings on your command line. You can set this by adding the line "set -o vi" to your ~/.bashrc.

Outro

There are many, many more intricacies to bash but I hope that this article has given you an insight into just how quick and easy using the command line can be. Once you spend a bit of time with your keyboard and an xterm you'll wonder what you ever saw in your mouse and those cumbursome dialog boxes. Don't forget, a quick reference chart to the shortcuts covered in this article is available here (opens a new window).

Until next time!

* Tell me you're not here because you pressed Ctrl-s right. You did didn't you? Well, OK, just this once. The combination you're looking for is Ctrl-q.





Save This Page
mikepeters See mikepeters' photos on flickr
Created with Vim   Graphics by GIMP