Appendix C. A Sample .bashrc File

The ~/.bashrc file determines the behavior of the shell, and of shell scripts. A proper understanding of this file can lead to more effective use of scripts.

Emmanuel Rouat contributed the following very elaborate .bashrc file. He wrote it for a Solaris system, but it (mostly) works for other flavors of UNIX as well. Study this file carefully, and feel free to reuse code snippets and functions from it in your own .bashrc file and even in your scripts.


Example C-1. Sample .bashrc file

   1 #===============================================================
   2 #
   3 # PERSONAL $HOME/.bashrc FILE for bash-2.04 (or later) 
   4 #              by Emmanuel Rouat
   5 #
   6 # This file is read (normally) by interactive shells only.
   7 # Here is the place to define your aliases, functions and
   8 # other interactive features like your prompt.
   9 # 
  10 # This file was designed for Solaris 
  11 #
  12 #===============================================================
  13 
  14 
  15 
  16 #-----------------------------------
  17 # Source global definitions (if any)
  18 #-----------------------------------
  19 
  20 if [ -f /etc/bashrc ]; then
  21 	. /etc/bashrc  # Read system bash init file, if exists.
  22 fi
  23 
  24 
  25 #-------------------------------------------------------------
  26 # Automatic setting of $DISPLAY (if not set already)
  27 # This works for linux and solaris - your mileage may vary....
  28 #-------------------------------------------------------------
  29 
  30 
  31 if [ -z ${DISPLAY:=""} ]; then
  32     DISPLAY=$(who am i)
  33     DISPLAY=${DISPLAY%%\!*}
  34     if [ -n "$DISPLAY" ]; then
  35 	export DISPLAY=$DISPLAY:0.0
  36     else
  37 	export DISPLAY=":0.0"  # fallback    
  38     fi
  39 fi
  40 
  41 
  42 #---------------
  43 # Some settings
  44 #---------------
  45 
  46 set -o notify
  47 set -o noclobber
  48 set -o ignoreeof
  49 set -o nounset
  50 #set -o xtrace		# useful for debuging 
  51 
  52 shopt -s cdspell 
  53 shopt -s cdable_vars
  54 shopt -s checkhash 
  55 shopt -s checkwinsize 
  56 shopt -s mailwarn
  57 shopt -s sourcepath
  58 shopt -s no_empty_cmd_completion
  59 shopt -s histappend histreedit
  60 shopt -s extglob	# useful for programmable completion
  61 
  62 
  63 
  64 #-----------------------
  65 # Greeting, motd etc...
  66 #-----------------------
  67 
  68 # Define some colors first:
  69 red='\e[0;31m'
  70 RED='\e[1;31m'
  71 blue='\e[0;34m'
  72 BLUE='\e[1;34m'
  73 cyan='\e[0;36m'
  74 CYAN='\e[1;36m'
  75 NC='\e[0m'		# No Color
  76 
  77 # Looks best on a black background.....
  78 echo -e "${CYAN}This is BASH ${RED}${BASH_VERSION%.*}${CYAN} - DISPLAY on ${RED}$DISPLAY${NC}\n"
  79 date
  80 
  81 
  82 function _exit()	# function to run upon exit of shell
  83 {
  84     echo -e "${RED}Hasta la vista, baby${NC}"
  85 }
  86 trap _exit 0
  87 
  88 #---------------
  89 # Shell prompt
  90 #---------------
  91 
  92 
  93 function fastprompt()
  94 {
  95     unset PROMPT_COMMAND
  96     case $TERM in
  97 	xterm | rxvt | dtterm )	
  98 	    PS1="[\h] \W > \[\033]0;[\u@\h] \w\007\]" ;;
  99 	*) 
 100 	    PS1="[\h] \W > " ;;
 101     esac
 102 }
 103 
 104 
 105 function powerprompt()
 106 {
 107     _powerprompt() 
 108     { 
 109 	LOAD=$(uptime|sed -e "s/.*: \([^,]*\).*/\1/" -e "s/ //g")	
 110 	TIME=$(date +%H:%M)
 111     } 
 112   
 113     PROMPT_COMMAND=_powerprompt
 114     case $TERM in
 115 	xterm | dtterm | rxvt  )
 116 	    PS1="${cyan}[\$TIME \$LOAD]$NC\n[\h \#] \W > \[\033]0;[\u@\h] \w\007\]" ;;
 117 	linux )
 118 	    PS1="${cyan}[\$TIME - \$LOAD]$NC\n[\h \#] \w > " ;;
 119 	* )
 120 	    PS1="[\$TIME - \$LOAD]\n[\h \#] \w > " ;;
 121     esac
 122 }
 123 
 124 powerprompt	# this is the default prompt - might be slow
 125 		# If too slow, use fastprompt instead....
 126 
 127 
 128 
 129 #===============================================================
 130 #
 131 # ALIASES AND FUNCTIONS 
 132 #
 133 # Arguably, some functions defined here are quite big 
 134 # (ie 'lowercase') but my workstation has 512Meg of RAM, so .....
 135 # If you want to make this file smaller, these functions can
 136 # be converted into scripts.
 137 #
 138 #===============================================================
 139 
 140 #-------------------
 141 # Personnal Aliases
 142 #-------------------
 143 
 144 alias rm='rm -i'
 145 alias cp='cp -i'
 146 alias mv='mv -i'
 147 alias h='history'
 148 alias j='jobs -l'
 149 alias r='rlogin'
 150 alias which='type -a'
 151 alias ..='cd ..'
 152 alias path='echo -e ${PATH//:/\\n}'
 153 alias print='/usr/bin/lp -o nobanner -d $LPDEST'
 154 
 155 alias la='ls -Al'
 156 alias lr='ls -lR'
 157 alias lt='ls -ltr'  
 158 alias lm='ls -al |more'
 159 
 160 # spelling typos
 161 
 162 alias xs='cd'
 163 alias vf='cd'
 164 alias moer='more'
 165 alias moew='more'
 166 alias kk='ll'
 167 
 168 
 169 #-----------------------------------------
 170 # Environment dependent aliases/variables
 171 #-----------------------------------------
 172 
 173 
 174 if [ -d $FREE/bin ] ; then	# use gnu/free stuff
 175 # Condition test unnecessary on a Linux or BSD system.
 176 
 177     alias vi='vim'
 178     alias csh='tcsh'
 179     alias du='du -h'
 180     alias df='df -kh'
 181     alias ls='ls -hF --color'
 182     alias lx='ls -lXB'
 183     alias lk='ls -lSr'
 184     alias pjet='enscript -h -G -fCourier9 -d $LPDEST '
 185     alias background='xv -root -quit -max -rmode 5'
 186 
 187     alias more='less'
 188     export PAGER=less
 189     export LESSCHARSET='latin1'
 190     export LESSOPEN='|lesspipe.sh %s'
 191     export LESS='-i  -e -M -X -F -R -P%t?f%f \
 192 :stdin .?pb%pb\%:?lbLine %lb:?bbByte %bb:-...'
 193 
 194 else				# use regular solaris stuff
 195 
 196     alias df='df -k'
 197     alias ls='ls -F'
 198 
 199 fi
 200 
 201 
 202 #----------------
 203 # a few fun ones
 204 #----------------
 205 
 206 function xtitle () 
 207 { 
 208     case $TERM in
 209 	xterm* | dtterm | rxvt) 
 210 	    echo -n -e "\033]0;$*\007" ;;
 211 	*)  ;;
 212     esac
 213 }
 214 
 215 alias top='xtitle Processes on $HOST && top'
 216 alias make='xtitle Making $(basename $PWD) ; make'
 217 alias ncftp="xtitle ncFTP ; ncftp"
 218 
 219 
 220 #---------------
 221 # and functions
 222 #---------------
 223 
 224 function man ()
 225 {
 226     xtitle The $(basename $1|tr -d .[:digit:]) manual
 227     /usr/bin/man -a "$*"
 228 }
 229 
 230 #-----------------------------------------
 231 # Environment dependent functions
 232 #-----------------------------------------
 233 
 234 # Note: we mustn't mix these with alias definitions in the same 'if/fi'
 235 # construct because alias expansion wouldn't occur in some functions here, 
 236 # like 'll' that uses ls (which is an alias).
 237 
 238 
 239 if [ -d $FREE/bin ] ; then	# use gnu/free stuff
 240 
 241     function ll(){ ls -l  $*| egrep "^d" ; ls -lh  $* 2>&-| egrep -v "^d|total "; }
 242     function xemacs() { { command xemacs -private $* 2>&- & } && disown ;}
 243     function te()  # wrapper around xemacs/gnuserv
 244     {
 245 	if [ "$(gnuclient -batch -eval t 2>&-)" == "t" ]; then
 246 	    gnuclient -q $@;
 247 	else
 248 	    ( xemacs $@ & );
 249 	fi
 250     }
 251 
 252 else				# use solaris stuff
 253 
 254     function ll(){ ls -l $* |egrep "^d"; ls -l $* 2>&- |egrep -v "^d|total" ;}
 255     function lk() { \ls -lF  $* | egrep -v "^d|^total" | sort -n -k 5,5 ;}    
 256     function te() { ( dtpad "$@" &)  ;}
 257 
 258 fi
 259 
 260 
 261 #-----------------------------------
 262 # File & strings related functions:
 263 #-----------------------------------
 264 
 265 function ff() { find . -name '*'$1'*' ; }
 266 function fe() { find . -name '*'$1'*' -exec $2 {} \; ; }
 267 function fstr() # find a string in a set of files
 268 {
 269     if [ "$#" -gt 2 ]; then
 270         echo "Usage: fstr \"pattern\" [files] "
 271     return;
 272     fi
 273     find . -type f -name "${2:-*}" -print | xargs grep -n "$1"
 274 }
 275 function cuttail() # cut last n lines in file
 276 {
 277     nlines=$1
 278     sed -n -e :a -e "1,${nlines}!{P;N;D;};N;ba" $2 
 279 }
 280 
 281 function lowercase()  # move filenames to lowercase
 282 {
 283     for file ; do
 284         filename=${file##*/}
 285         case "$filename" in
 286         */*) dirname==${file%/*} ;;
 287         *) dirname=.;;
 288         esac
 289         nf=$(echo $filename | tr A-Z a-z)
 290         newname="${dirname}/${nf}"
 291         if [ "$nf" != "$filename" ]; then
 292             mv "$file" "$newname"
 293             echo "lowercase: $file --> $newname"
 294         else
 295             echo "lowercase: $file not changed."
 296         fi
 297     done
 298 }
 299 
 300 function swap()		# swap 2 filenames around
 301 {
 302     local TMPFILE=tmp.$$
 303     mv $1 $TMPFILE
 304     mv $2 $1
 305     mv $TMPFILE $2
 306 }
 307 
 308 
 309 # Process/system related functions:
 310 
 311 alias my_ps='/usr/bin/ps -u "$USER" -o user,pid,ppid,pcpu,pmem,args'
 312 function pp() { my_ps | nawk '!/nawk/ && $0~pat' pat=${1:-".*"} ; }
 313 function killps()	# Kill process by name
 314 {			# works with gawk too
 315     local pid pname sig="-TERM" # default signal
 316     if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then 
 317 	echo "Usage: killps [-SIGNAL] pattern"
 318 	return;
 319     fi
 320     if [ $# = 2 ]; then sig=$1 ; fi
 321     for pid in $(my_ps | nawk '!/nawk/ && $0~pat { print $2 }' pat=${!#}) ; do
 322 	pname=$(my_ps | nawk '$2~var { print $6 }' var=$pid )
 323 	if ask "Kill process $pid <$pname> with signal $sig ? "
 324 	    then kill $sig $pid
 325 	fi
 326     done
 327 }
 328 
 329 function ii()   # get current host related info
 330 {
 331     echo -e "\nYou are logged on ${RED}$HOST"
 332     echo -e "\nAdditionnal information:$NC " ; uname -a
 333     echo -e "\n${RED}IP Address :$NC" ; ypmatch $HOSTNAME hosts
 334     echo -e "\n${RED}Users logged on:$NC " ; /usr/ucb/users
 335     echo -e "\n${RED}Current date :$NC " ; date
 336     echo -e "\n${RED}Machine stats :$NC " ; uptime
 337     echo -e "\n${RED}Memory stats :$NC " ; vmstat
 338     echo -e "\n${RED}NIS Server :$NC " ; ypwhich
 339     echo
 340 }
 341 function corename()   # get name of app that created core
 342 {
 343     local file name;
 344     file=${1:-"core"}
 345     set -- $(adb $file < /dev/null 2>&1 | sed 1q)
 346     name=${7#??}
 347     echo $file: ${name%??}
 348 }
 349 # Misc utilities:
 350 
 351 function repeat()	# repeat n times command
 352 {
 353     local i max
 354     max=$1; shift;
 355     for ((i=1; i <= max ; i++)); do
 356 	eval "$@";
 357     done
 358 }
 359 	
 360 
 361 function ask()
 362 {
 363     echo -n "$@" '[y/n] ' ; read ans
 364     case "$ans" in
 365         y*|Y*) return 0 ;;
 366         *) return 1 ;;
 367     esac
 368 }
 369 
 370 
 371 
 372 #=========================================================================
 373 #
 374 # PROGRAMMABLE COMPLETION - ONLY IN BASH-2.04
 375 #
 376 #=========================================================================
 377 
 378 if [ "${BASH_VERSION%.*}" \< "2.04" ]; then
 379     echo "No programmable completion available"
 380     return
 381 fi
 382    
 383 shopt -s extglob	# necessary
 384 
 385 complete -A hostname   rsh rcp telnet rlogin r ftp ping disk
 386 complete -A command    nohup exec eval trace truss strace sotruss gdb
 387 complete -A command    command type which 
 388 complete -A export     printenv
 389 complete -A variable   export local readonly unset
 390 complete -A enabled    builtin
 391 complete -A alias      alias unalias
 392 complete -A function   function
 393 complete -A user       su mail finger
 394 
 395 complete -A helptopic  help	# currently same as builtins
 396 complete -A shopt      shopt
 397 complete -A stopped -P '%' bg
 398 complete -A job -P '%'     fg jobs disown
 399 
 400 complete -A directory  mkdir rmdir
 401 
 402 complete -f -X '*.gz'   gzip
 403 complete -f -X '!*.ps'  gs ghostview gv
 404 complete -f -X '!*.pdf' acroread
 405 complete -f -X '!*.+(gif|jpg|jpeg|GIF|JPG|bmp)' xv gimp
 406 
 407  
 408 _make_targets ()
 409 {
 410     local mdef makef gcmd cur prev i
 411 
 412     COMPREPLY=()
 413     cur=${COMP_WORDS[COMP_CWORD]}
 414     prev=${COMP_WORDS[COMP_CWORD-1]}
 415 
 416     # if prev argument is -f, return possible filename completions.
 417     # we could be a little smarter here and return matches against
 418     # `makefile Makefile *.mk', whatever exists
 419     case "$prev" in
 420 	-*f)	COMPREPLY=( $(compgen -f $cur ) ); return 0;;
 421     esac
 422 
 423     # if we want an option, return the possible posix options
 424     case "$cur" in
 425 	-)	COMPREPLY=(-e -f -i -k -n -p -q -r -S -s -t); return 0;;
 426     esac
 427 
 428     # make reads `makefile' before `Makefile'
 429     if [ -f makefile ]; then
 430 	mdef=makefile
 431     elif [ -f Makefile ]; then
 432 	mdef=Makefile
 433     else
 434 	mdef=*.mk		# local convention
 435     fi
 436 
 437     # before we scan for targets, see if a makefile name was specified
 438     # with -f
 439     for (( i=0; i < ${#COMP_WORDS[@]}; i++ )); do
 440 	if [[ ${COMP_WORDS[i]} == -*f ]]; then
 441 	    eval makef=${COMP_WORDS[i+1]}	# eval for tilde expansion
 442 	    break
 443 	fi
 444     done
 445 
 446 	[ -z "$makef" ] && makef=$mdef
 447 
 448     # if we have a partial word to complete, restrict completions to
 449     # matches of that word
 450     if [ -n "$2" ]; then gcmd='grep "^$2"' ; else gcmd=cat ; fi
 451 
 452     # if we don't want to use *.mk, we can take out the cat and use
 453     # test -f $makef and input redirection	
 454     COMPREPLY=( $(cat $makef 2>/dev/null | awk 'BEGIN {FS=":"} /^[^.# 	][^=]*:/ {print $1}' | tr -s ' ' '\012' | sort -u | eval $gcmd ) )
 455 }
 456 
 457 complete -F _make_targets -X '+($*|*.[cho])' make gmake pmake
 458 
 459 
 460 _configure_func ()
 461 {
 462     case "$2" in
 463 	-*)	;;
 464 	*)	return ;;
 465     esac
 466 
 467     case "$1" in
 468 	\~*)	eval cmd=$1 ;;
 469 	*)	cmd="$1" ;;
 470     esac
 471 
 472     COMPREPLY=( $("$cmd" --help | awk '{if ($1 ~ /--.*/) print $1}' | grep ^"$2" | sort -u) )
 473 }
 474 
 475 complete -F _configure_func configure
 476 
 477 _killps ()
 478 {
 479     local cur prev
 480     COMPREPLY=()
 481     cur=${COMP_WORDS[COMP_CWORD]}
 482 
 483     # get a list of processes (the first sed evaluation
 484     # takes care of swapped out processes, the second
 485     # takes care of getting the basename of the process)
 486     COMPREPLY=( $( /usr/bin/ps -u $USER -o comm  | \
 487 	sed -e '1,1d' -e 's#[]\[]##g' -e 's#^.*/##'| \
 488 	awk '{if ($0 ~ /^'$cur'/) print $0}' ))
 489 
 490     return 0
 491 }
 492 complete -F _killps killps
 493 
 494 
 495 
 496 # Local Variables:
 497 # mode:shell-script
 498 # sh-shell:bash
 499 # End: