Introduction to Bash and Reality Check for Me:

I have to admit from the beginning that I need to take the time to expand my own bash profiles.  I find myself hitting ‘up’ to scroll through mounds of history or doing the famous ‘history | grep <whatever>’ to find commands and obscure options that instead could be a key or two away.  Like many developers, I find myself bouncing from server to server or laptop to desktop and I have let this be my excuse for not getting too close to my .bashrc (don’t worry if you are not familiar with that yet).  This inefficiency has been highlighted in a lot of posts on Reddit lately but I think my motivation came mostly from the comments and article here: Bash-isms I wish I Knew Earlier.

Bash is a Unix shell written by Brian Fox for the GNU Project as a replacement for the Bourne shell (sh).  I stole that line almost directly from Wikipedia.  It is now the standard for Linux and Mac OSX.  There are other shells out there but this one is mine.  Most people new to computers call it the ‘DOS prompt’, ‘Command Prompt’, ‘Black screen’ or possibly the most correct out of the bunch ‘Terminal’.  Bottom line, if you are logging in to a server via ssh for your hosting, you are probably using Bash.

Bash Shell .bashrc Tricks

To hold my own attention and probably yours, I will go straight to some examples.  Most users will be logging in as an ‘interactive non-login shell’ not as a ‘interactive login shell’.  Depending on how you are logged in, bash will look for and execute ‘~/.bashrc’ or ‘~/.profile’  (sometimes both).  These files can dictate the experience you have in bash and can add functionality to your bash world.  For my examples, I am updating my ‘~/.bashrc’.

Looking in my shell history, there are two things that I do over and over.  The first, ssh’ing to other machines and the second, changing to a different directory with way to many keystrokes.  Both tasks that can be simplified by adding using alias in our ‘.bashrc’ file.  I want to go to the root working directory of Thomasloughlin.com and I only want to type ‘tl’.  It would look like this:

alias tl='cd /srv/www/realm1/thomasloughlin.com/public_html'

Other examples:
alias tlweb='ssh [email protected]'

alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
alias h='history'
alias j='jobs -l'
alias which='type -a'
alias ..='cd ..'
alias path='echo -e ${PATH//:/\\n}'

The concept is always the same – alias <name>=<command>.

In the comments from the Bash-ism blog, kanzeryu, also suggested this helpful aliasing function:

a() { alias $1=cd\ $PWD; }

It allows you to type ‘a <variable>’ and save your current directory temporarily to the variable you supplied.  The next time you need to go back to that directory, you just type the variable.

Kanzeryu also brings us to the next topic, functions.

Functions in .bashrc

Functions are pretty straightforward if you are familiar with any other programming language.  With a function, you have a set of instructions that you want to reuse over and over on different supplied inputs.  For example, I care about the weather and need to be able to type ‘weather <zip code>’ and have the latest forecast.  I can do that with the following bash function:

weather ()
{
lynx -dump "http://www.weather.com/weather/print/{$1}"
}

This example is pretty basic (and there are much prettier ways to get the weather in bash).

Other function examples from Emmanual Rouat:

# Find a file with a pattern in name:
function ff() { find . -type f -iname '*'$*'*' -ls ; }

# Find a file with pattern $1 in name and Execute $2 on it:
function fe()
{ find . -type f -iname '*'${1:-}'*' -exec ${2:-file} {} \; ; }

# Find a pattern in a set of files and highlight them:
# (needs a recent version of egrep)
function fstr()
{
 OPTIND=1
 local case=""
 local usage="fstr: find string in files.
Usage: fstr [-i] \"pattern\" [\"filename pattern\"] "
 while getopts :it opt
 do
 case "$opt" in
 i) case="-i " ;;
 *) echo "$usage"; return;;
 esac
 done
 shift $(( $OPTIND - 1 ))
 if [ "$#" -lt 1 ]; then
 echo "$usage"
 return;
 fi
 find . -type f -name "${2:-*}" -print0 | \
 xargs -0 egrep --color=always -sn ${case} "$1" 2&gt;&amp;- | more
}

function cuttail() # cut last n lines in file, 10 by default
{
 nlines=${2:-10}
 sed -n -e :a -e "1,${nlines}!{P;N;D;};N;ba" $1
}

function lowercase() # move filenames to lowercase
{
 for file ; do
 filename=${file##*/}
 case "$filename" in
 */*) dirname==${file%/*} ;;
 *) dirname=.;;
 esac
 nf=$(echo $filename | tr A-Z a-z)
 newname="${dirname}/${nf}"
 if [ "$nf" != "$filename" ]; then
 mv "$file" "$newname"
 echo "lowercase: $file --&gt; $newname"
 else
 echo "lowercase: $file not changed."
 fi
 done
}

function swap() # Swap 2 filenames around, if they exist
{ #(from Uzi's bashrc).
 local TMPFILE=tmp.$$

[ $# -ne 2 ] &amp;&amp; echo "swap: 2 arguments needed" &amp;&amp; return 1
 [ ! -e $1 ] &amp;&amp; echo "swap: $1 does not exist" &amp;&amp; return 1
 [ ! -e $2 ] &amp;&amp; echo "swap: $2 does not exist" &amp;&amp; return 1

mv "$1" $TMPFILE 
 mv "$2" "$1"
 mv $TMPFILE "$2"
}

function extract() # Handy Extract Program.
{
 if [ -f $1 ] ; then
 case $1 in
 *.tar.bz2) tar xvjf $1 ;;
 *.tar.gz) tar xvzf $1 ;;
 *.bz2) bunzip2 $1 ;;
 *.rar) unrar x $1 ;;
 *.gz) gunzip $1 ;;
 *.tar) tar xvf $1 ;;
 *.tbz2) tar xvjf $1 ;;
 *.tgz) tar xvzf $1 ;;
 *.zip) unzip $1 ;;
 *.Z) uncompress $1 ;;
 *.7z) 7z x $1 ;;
 *) echo "'$1' cannot be extracted via &gt;extract&lt;" ;;
 esac
 else
 echo "'$1' is not a valid file"
 fi
}

And that is the end of Part 1.  Next up: color formatting and short-cut keys.


Leave a Reply