Increasing command line productivity in the bash shell PT: II

by Jeff on June 13, 2008

In the first bash tutorial we went over brace expansions and a few history tricks. The goal of this post is to expand on that and teach more bash features.

Have you ever wondered when you typed a previous command in your history? This is easy to do with the $HISTTIMEFORMAT variable and bash >= 3.0. $HISTTIMEFORMAT accepts standard strftime(3) format strings.

jeff@beastmaster:~$ export HISTTIMEFORMAT="%m/%d/%y - %H:%M:%S "
jeff@beastmaster:~$ history | tail -n 75
411  06/11/08 - 15:36:09 sudo apt-get install network-manager-dev libmozjs-dev libmozjs0d
412  06/11/08 - 15:36:22 make clean && ./configure
413  06/11/08 - 15:36:30 make
414  06/11/08 - 15:36:54 apt-cache search dbus
415  06/11/08 - 15:36:59 apt-cache search dbus | grep dev

NOTE: The first time you set $HISTTIMEFORMAT, all previous commands inherit the current time. Everything afterwards is saved with a proper timestamp.

In the previous tutorial we covered usage of shell history modifiers like !vi or !?passwd to run previous commands. The only problem with those is that they execute the command directly without letting you edit them. Enabling the histverify shell option lets you edit the command before running it.

jeff@beastmaster:~$ shopt -s histverify
jeff@beastmaster:~$ !vi
jeff@beastmaster:~$ vi src/libproxy/src/Makefile

$CDPATH is a variable similar to $PATH, but it defines a search path for the cd command.

Given a directory structure like below, lets say that /home/jeff/svn/systems is one of your most frequently accessed directories.

/home/jeff/svn

/home/jeff/svn/systems
jeff@beastmaster:~$ export CDPATH=/home/jeff/svn
jeff@beastmaster:~$ pwd
/home/jeff
jeff@beastmaster:~$ cd systems
/home/jeff/svn/systems
jeff@beastmaster:~/svn/systems$ pwd
/home/jeff/svn/systems

Cool huh? The last set of tricks for today are bash's powerful parameter substitutions. Here is a non-exhaustive list along with a few examples. The open group has further information on all possible parameter expansions in posix compatible shells.

${parameter:-word} Substitute word if parameter is null or non-s
et. Otherwise, use $parameter as normal.
${parameter:=word} If $parameter is unset of null, set the value
to word and substitute it's value in-place.
${parameter:+word} If $parameter is set and non-null, substitute
word. Otherwise, substitute nothing.
${parameter/foo/bar} If parameter is set and contains the value
foo, replace foo with bar and print the result.
jeff@beastmaster:~$ jeff@beastmaster:~$ parameter=digitalprognosis.com
jeff@beastmaster:~$ echo $parameter
digitalprognosis.com
jeff@beastmaster:~$ unset parameter
jeff@beastmaster:~$ echo $parameter # Empty

jeff@beastmaster:~$ echo ${parameter:-linux.com} # Display, but don't set the variable
linux.com
jeff@beastmaster:~$ echo $parameter # Empty

jeff@beastmaster:~$ echo ${parameter:=ubuntu.com} # Sets parameter to ubuntu.com
ubuntu.com
jeff@beastmaster:~$ echo $parameter
ubuntu.com
jeff@beastmaster:~$ echo ${parameter:+redhat.com} # Displays because parameter is set
redhat.com
jeff@beastmaster:~$ echo $parameter
ubuntu.com
jeff@beastmaster:~$ echo ${parameter/ubuntu/canonical} # Very simple sed feature-set
canonical.com
jeff@beastmaster:~$ echo $parameter
ubuntu.com

{ 2 comments… read them below or add one }

1 Rasta Freak 07.17.08 at 10:26 am

Nice tips, Jeff. I’d like to see more of this :)
Anyway, just one note:

when using parameter substitution (:-, :+, :=), i think that one more thing needs to be said: if you use it with “:” sign (:-, :+, :=) then it checks if parameter is unset (set) OR null (if var is set to NULL value, var is considered unset). If you use it without “:” character (-,+,=), it checks only if parameter is set (unset) (if var is set to NULL value, var is considered set).

2 Jeff 07.17.08 at 12:10 pm

From this post, “${parameter:-word} Substitute word if parameter is null or non-set. Otherwise, use $parameter as normal.”

You bring up a good point, but I already said the same thing :)

Leave a Comment

You can use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Previous post:

Next post: