Customizing the Terminal: 5 Configuration Settings in Bash that makes you a CLI Power User

Written by BinnyVA on April 13, 2009 – 1:10 am -

Terminal

There are some settings that are very useful if you work on the terminal a lot. Many of the cool ones are not enabled by default – this is a small list of the configuration settings that I use to make my terminal usage more productive.

This is part 3 of the Customizing the Terminal series. Already published posts in this series are…

1. Case Correction

I like to title case my folders and files’ names. The folders in my home are ‘Scripts’, ‘Documents’, ‘Temp’ etc. The first character is in upper case. But when I work on the command line, I don’t always remember to uppercase the first character when trying to cd into a folder. Consequently, the tabbing will not work. Fortunately, there is an option that auto corrects the case for you. Just open a terminal and type in this command…

shopt -s nocaseglob

Other useful shopt option are…

cdspell
Corrects typos in your file/directory name.
histappend
Makes sure that histories in multiple simultaneous shells don’t overwrite each other.

2. Select Which Commands to Store in History

By default, all commands you type in are stored in the history. You can pick and chose the commands you want to store by putting the option…

export HISTCONTROL=ignorespace

in your ~/.bash_profile file. This will make sure that bash don’t store any command beginning with the space character. So if you want bash to forget that you typed in ‘ls’, just type in ‘ ls'(<space>ls).

3. Don’t Store Duplicate Commands in your History

As I said earlier, all commands you type are stored – even the duplicate ones. You can prevent this by putting this text in your .bash_profile file…

export HISTCONTROL=ignoredups

If you want to ignore spaced commands and want to prevent storing of duplicate commands, use the option…

export HISTCONTROL=ignoreboth

4. Auto-complete Command from History

Picture this – you type in ‘ssh’ and press the ‘Page Up’ key – and bash automatically fetches the last command that starts with ssh – and completes the command for you. Well, its possible – add the following line in your ‘.bash_profile’ file…

export INPUTRC=$HOME/.inputrc

Now, create a file called .inputrc in your home and enter this into it…

#Page up/page down
"\e[5~": history-search-backward
"\e[6~": history-search-forward

Yes, I am aware of the up Ctrl+R trick – that comes in the next post.

5. Infinite History

You can increase or decrease the size of the history by adding this line in the .bash_profile file…

export HISTSIZE=500
export HISTFILESIZE=500

This will limit the commands to be stored in the history to 500. If you want to remove the limit use these lines…

unset HISTSIZE
unset HISTFILESIZE

There is a good chance that this will make your history file quite huge – use with care.

Please share your configuration settings for bash in the comments.

Related Links


Tags: , , , , , , ,
Posted in Command Line, Configuration | 6 Comments »

Customizing the Terminal: The Prompt

Written by BinnyVA on March 10, 2009 – 11:34 pm -

Terminal

Most Linux ‘gurus’ spend a lot of time working in the terminal. If you belong to that group, this post is for you. This is a tutorial to configure the terminal prompt to the best possible value for your use. Note: This tutorial is for bash users – these instructions will not work in other shells.

The Prompt

You must have seen the prompt if you have use the terminal – it is the first few characters in each line. Usually, it will be…

[username@localhost] ~ $

In this case, the user is shown three piece of information in the prompt –

  • Username of the current user
  • Hostname
  • Current folder name

This post will show you how to customize this prompt to your needs.

Editing the Prompt

Editing the prompt is very simple – you just have to edit a shell variable. To see the current prompt’s value, open a shell and type the command…

echo $PS1

The result will be something like this(in Ubuntu)…

binnyva@binlap:~$ echo $PS1
\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\u@\h:\w\$

Which is functionally the same as…

\u@\h:\W\$ 

To edit this variable, run the command…

export PS1=<New Prompt Value>

Most desktop systems don’t need the username and hostname in the prompt – this is only relevent if your are connected to a remote system. So the first thing to do, if you are on a desktop system, is to remove those two. To do that, run the command…

export PS1="[\W]\$ "

This will change the prompt in the current terminal. To make it permanent, edit the ~/.bashrc and set the PS1 variable there. Just add this line at the end of the file…

export PS1="[\W]\$ "

A Better Prompt

Currently, the prompt has the basename of the current working directory. That is, if we are in ‘~/Sites/Lindesk/posts’, the prompt will be ‘[posts]$ ‘. This is good enough for most people. But I have a problem with this. If I go to another folder, say, ‘~/Sites/OpenJS/posts’, the prompt is still ‘[posts]$ ‘. The prompt is a bit ambiguous in this case. This can be done using a different character – in this case \w(small ‘w’ – the default was capital ‘W’).

[posts]$ export PS1="[\w]$ "
[~/Sites/OpenJS/posts]$ _

This is nice – but you will have a problem if the directory you are in is several levels deep. It might be something like this…

[/var/www/html/sites/Lindesk/lindesk.com/wp-content/plugins/eventr/langs]$ _

That’s long – and inconvenient. There are better ways of doing this.

Show the Beginning and the End.

A better way of doing this is to cut of a part of the folder – so the above path will look something like…

[/var/www/html.../eventr/langs] $ _

This option will show the first 15 characters of the path and then the last 15 characters – if the directory path is bigger than 30 characters. To enable this mode, open up the file ~/.bashrc and add this code…

PROMPT_COMMAND='DIR=`pwd|sed -e "s!$HOME!~!"`; if [ ${#DIR} -gt 30 ]; then CurDir=${DIR:0:12}...${DIR:${#DIR}-15}; else CurDir=$DIR; fi'
PS1="[\$CurDir] \$ "

The First Character of Each Directory

There is yet another method – I got this idea from the fish shell. In this approach, the big path will appear as…

[/v/w/h/s/L/l/w/p/e/langs] $ _

In this option, only the first character of each parent folder will be shown. Only the base folder name will be shown entirely. This is the approach I use. If you want to use this, open the ~/.bashrc file and add this…

PROMPT_COMMAND='CurDir=`pwd|sed -e "s!$HOME!~!"|sed -re "s!([^/])[^/]+/!\1/!g"`'
PS1="[\$CurDir] \$ "

Prompt Variables

The other values you can insert into the prompt are…

\d
the date in “Weekday Month Date” format (e.g., “Tue May 26”)
\D{format}
the format is passed to strftime(3) and the result is inserted into the prompt string; an empty format results in a locale-specific time representation. The braces are required
\e
an ASCII escape character (033)
\h
the hostname up to the first ‘.’
\H
the hostname
\j
the number of jobs currently managed by the shell
\l
the basename of the shell’s terminal device name
\n
newline
\r
carriage return
\s
the name of the shell, the basename of $0 (the portion following the final slash)
\t
the current time in 24-hour HH:MM:SS format
\T
the current time in 12-hour HH:MM:SS format
\@
the current time in 12-hour am/pm format
\A
the current time in 24-hour HH:MM format
\u
the username of the current user
\v
the version of bash (e.g., 2.00)
\V
the release of bash, version + patch level (e.g., 2.00.0)
\w
the current working directory, with $HOME abbreviated with a tilde
\W
the basename of the current working directory, with $HOME abbreviated with a tilde
\!
the history number of this command
\#
the command number of this command
\$
if the effective UID is 0, a #, otherwise a $
\nnn
the character corresponding to the octal number nnn
\\
a backslash
\[
begin a sequence of non-printing characters, which could be used to embed a terminal control sequence into the prompt
\]
end a sequence of non-printing characters

Tags: , , , , ,
Posted in Command Line, Configuration | 22 Comments »

Shell Script Language – Use Perl, Not Bash

Written by BinnyVA on May 2, 2008 – 11:40 pm -

To me, a shell script is a script that automates repetitive tasks. But that is not the ‘official’ definition. Wikipedia has this definition

A shell script is a script written for the shell, or command line interpreter, of an operating system.

I use a definition that defines the purpose of the script – while the others prefer a definition that defines the technology used. I am not going to claim that my definition is better than the other definition – that’s pointless. Besides, even I think that the ‘other’ definition is the right one. But I will try to show you the advantages of my approach.

The Purpose

I like to automate things(in other words, I’m lazy). So I have a nice little collection of custom shell scripts. But there is a huge barrier to writing shell scripts – the language used. Traditionally shell scripts are written in a language provided by the shell – like bash or tcsh. That is the problem – these languages are Bad – with a capital ‘B’.

The Problem

To people who are accustomed to decent languages, these shell languages will seem clunky – or even evil. But since most shell scripts are small, most people don’t mind the torture.

In bash, the control flow commands seem to be thrown in as a after thought rather than something that’s built into the language. If you don’t believe me, compare the ‘if’ loop of bash and Perl.

Bash

This code checks wether the variable ‘$value’ has the value 0 – if so it prints the message ‘No Value’

if [ $value -eq 0 ] ; then
	echo "No Value"
fi

Perl

The same code in Perl…

if($value == 0) {
	print "No Value";
}

Of course, Perl experts will go for if(!$value) or even unless($value) – but that’s not the point. See how better the code looks in Perl. Yeah, even I am surprised to hear those words – Perl is considered by many to be an ‘ugly’ language. But when compared to shell languages, Perl is a gem(sorry about the pun – couldn’t resist).

The Solution

The solution is simple – don’t use a shell language to write your shell scripts – use a high level scripting language like Perl. Or Python, Ruby, PHP, Tcl or even JavaScript.

I still use bash to write shell scripts – but if the shell script has an if condition(other than a simple argument check), I use a higher language – usually Perl.

Advantages of using a Shell Language

  • Its supported in even the tinest linux distros – even in embedded systems.
  • Its the method preferred by the majority – I hope this will change soon.
  • Command calls look more natural in a shell language.

Advantages of using a High Level Language

  • Better Code
  • Easy to maintain
  • Faster development
  • Libraries provide a lot of functionality
  • Easier to port to different platforms.

So why am I telling you all this? Two reasons…

One, the next time you are going to write a shell script, I want you to choose a high level language rather than using bash.

The second reason is that now that my series on Linux MP3 Players are over, I am going to take a small break from desktop posts and write on more ‘linuxy’ topics. And one of those topic is Shell Scripting. So in the future posts, I am going to share some of my shell scripts with you. So when I publish a Perl script and call it a shell script, I don’t want you to get confused .

Update: This article is translated to Serbo-Croatian language.


Tags: , , , , ,
Posted in Command Line, Programming, Scripting | 42 Comments »

fish(Friendly Interactive Shell)

Written by BinnyVA on April 8, 2007 – 1:00 pm -

fish(Friendly Interactive Shell) is a new shell for Linux. I tried it out and have decided to dump bash for fish. Try it out – you will come to the same conclusion as well.

Features of fish

Syntax Coloring

The shell colorizes the commands as you type them – if it is a valid command it will have a green color. For example, lets say I want to see my network interfaces. Recently, I had a lot of use for that – but that is another post. So, I type ifconfig into the shell. When I am at ‘ifco’, the shell will be like this…

Ifco - Typing completion

When I have completed the command, ifconfig, the shell will be like this…

Completed

Strings, matching etc. are also highlighted as you type.

Syntax Highlighting

Tab Completion

You would not think that this is a new feature. Bash has tab completion. Even Windows XP’s DOS terminal has tab completion. But fish’s tab completion is no ordinary tab completion – think of it as tab completion on steroids.

fish’s tab completion implements a feature that I really needed – tab completion for subcommands. Subcommand is the command line argument that is given to some programs. For example,

yum update gimp
cvs commit file.php

In the first example, yum is the command an ‘update‘ is the subcommand. Just type ‘yum upd’ and press Tab to complete the command. Similarly in the second case cvs is the command and commit is the subcommand.

Many other completions are also supported…

  • Commands, both builtins, functions and regular programs.
  • Environment variable names (Eg. $HOME).
  • Usernames for tilde(~) expansion.
  • Filenames, even on strings with wildcards such as ‘*’, ‘**’ and ‘?’.
  • Job id, job name and process names for process expansion. This is very useful when using kill.

Enough talking. You can download the fish shell from their official website. For Red Hat/Fedora Core users, this command will do the trick.

yum install fish

If you are a debian or Ubuntu user, use this command

apt-get install fish


Tags: , , ,
Posted in Command Line, Tools | 5 Comments »