The ~/.bashrc file determines the behavior of interactive shells. A good look at this file can lead to a better understanding of Bash.
Emmanuel Rouat contributed the following very elaborate .bashrc file, written for a Linux system. He welcomes reader feedback on it.
Study the file carefully, and feel free to reuse code snippets and functions from it in your own .bashrc file or even in your scripts.
Example J-1. Sample .bashrc file
1 #===============================================================
2 #
3 # PERSONAL $HOME/.bashrc FILE for bash-2.05a (or later)
4 #
5 # Last modified: Tue Apr 15 20:32:34 CEST 2003
6 #
7 # This file is read (normally) by interactive shells only.
8 # Here is the place to define your aliases, functions and
9 # other interactive features like your prompt.
10 #
11 # This file was designed (originally) for Solaris but based
12 # on Redhat's default .bashrc file
13 # --> Modified for Linux.
14 # The majority of the code you'll find here is based on code found
15 # on Usenet (or internet).
16 # This bashrc file is a bit overcrowded - remember it is just
17 # just an example. Tailor it to your needs
18 #
19 #
20 #===============================================================
21
22 # --> Comments added by HOWTO author.
23 # --> And then edited again by ER :-)
24
25 #-----------------------------------
26 # Source global definitions (if any)
27 #-----------------------------------
28
29 if [ -f /etc/bashrc ]; then
30 . /etc/bashrc # --> Read /etc/bashrc, if present.
31 fi
32
33 #-------------------------------------------------------------
34 # Automatic setting of $DISPLAY (if not set already)
35 # This works for linux - your mileage may vary....
36 # The problem is that different types of terminals give
37 # different answers to 'who am i'......
38 # I have not found a 'universal' method yet
39 #-------------------------------------------------------------
40
41 function get_xserver ()
42 {
43 case $TERM in
44 xterm )
45 XSERVER=$(who am i | awk '{print $NF}' | tr -d ')''(' )
46 # Ane-Pieter Wieringa suggests the following alternative:
47 # I_AM=$(who am i)
48 # SERVER=${I_AM#*(}
49 # SERVER=${SERVER%*)}
50
51 XSERVER=${XSERVER%%:*}
52 ;;
53 aterm | rxvt)
54 # find some code that works here.....
55 ;;
56 esac
57 }
58
59 if [ -z ${DISPLAY:=""} ]; then
60 get_xserver
61 if [[ -z ${XSERVER} || ${XSERVER} == $(hostname) || ${XSERVER} == "unix" ]]; then
62 DISPLAY=":0.0" # Display on local host
63 else
64 DISPLAY=${XSERVER}:0.0 # Display on remote host
65 fi
66 fi
67
68 export DISPLAY
69
70 #---------------
71 # Some settings
72 #---------------
73
74 ulimit -S -c 0 # Don't want any coredumps
75 set -o notify
76 set -o noclobber
77 set -o ignoreeof
78 set -o nounset
79 #set -o xtrace # useful for debuging
80
81 # Enable options:
82 shopt -s cdspell
83 shopt -s cdable_vars
84 shopt -s checkhash
85 shopt -s checkwinsize
86 shopt -s mailwarn
87 shopt -s sourcepath
88 shopt -s no_empty_cmd_completion # bash>=2.04 only
89 shopt -s cmdhist
90 shopt -s histappend histreedit histverify
91 shopt -s extglob # necessary for programmable completion
92
93 # Disable options:
94 shopt -u mailwarn
95 unset MAILCHECK # I don't want my shell to warn me of incoming mail
96
97
98 export TIMEFORMAT=$'\nreal %3R\tuser %3U\tsys %3S\tpcpu %P\n'
99 export HISTIGNORE="&:bg:fg:ll:h"
100 export HOSTFILE=$HOME/.hosts # Put a list of remote hosts in ~/.hosts
101
102
103
104 #-----------------------
105 # Greeting, motd etc...
106 #-----------------------
107
108 # Define some colors first:
109 red='\e[0;31m'
110 RED='\e[1;31m'
111 blue='\e[0;34m'
112 BLUE='\e[1;34m'
113 cyan='\e[0;36m'
114 CYAN='\e[1;36m'
115 NC='\e[0m' # No Color
116 # --> Nice. Has the same effect as using "ansi.sys" in DOS.
117
118 # Looks best on a black background.....
119 echo -e "${CYAN}This is BASH ${RED}${BASH_VERSION%.*}${CYAN} - DISPLAY on ${RED}$DISPLAY${NC}\n"
120 date
121 if [ -x /usr/games/fortune ]; then
122 /usr/games/fortune -s # makes our day a bit more fun.... :-)
123 fi
124
125 function _exit() # function to run upon exit of shell
126 {
127 echo -e "${RED}Hasta la vista, baby${NC}"
128 }
129 trap _exit EXIT
130
131 #---------------
132 # Shell Prompt
133 #---------------
134
135 if [[ "${DISPLAY#$HOST}" != ":0.0" && "${DISPLAY}" != ":0" ]]; then
136 HILIT=${red} # remote machine: prompt will be partly red
137 else
138 HILIT=${cyan} # local machine: prompt will be partly cyan
139 fi
140
141 # --> Replace instances of \W with \w in prompt functions below
142 #+ --> to get display of full path name.
143
144 function fastprompt()
145 {
146 unset PROMPT_COMMAND
147 case $TERM in
148 *term | rxvt )
149 PS1="${HILIT}[\h]$NC \W > \[\033]0;\${TERM} [\u@\h] \w\007\]" ;;
150 linux )
151 PS1="${HILIT}[\h]$NC \W > " ;;
152 *)
153 PS1="[\h] \W > " ;;
154 esac
155 }
156
157 function powerprompt()
158 {
159 _powerprompt()
160 {
161 LOAD=$(uptime|sed -e "s/.*: \([^,]*\).*/\1/" -e "s/ //g")
162 }
163
164 PROMPT_COMMAND=_powerprompt
165 case $TERM in
166 *term | rxvt )
167 PS1="${HILIT}[\A \$LOAD]$NC\n[\h \#] \W > \[\033]0;\${TERM} [\u@\h] \w\007\]" ;;
168 linux )
169 PS1="${HILIT}[\A - \$LOAD]$NC\n[\h \#] \w > " ;;
170 * )
171 PS1="[\A - \$LOAD]\n[\h \#] \w > " ;;
172 esac
173 }
174
175 powerprompt # this is the default prompt - might be slow
176 # If too slow, use fastprompt instead....
177
178 #===============================================================
179 #
180 # ALIASES AND FUNCTIONS
181 #
182 # Arguably, some functions defined here are quite big
183 # (ie 'lowercase') but my workstation has 512Meg of RAM, so .....
184 # If you want to make this file smaller, these functions can
185 # be converted into scripts.
186 #
187 # Many functions were taken (almost) straight from the bash-2.04
188 # examples.
189 #
190 #===============================================================
191
192 #-------------------
193 # Personnal Aliases
194 #-------------------
195
196 alias rm='rm -i'
197 alias cp='cp -i'
198 alias mv='mv -i'
199 # -> Prevents accidentally clobbering files.
200 alias mkdir='mkdir -p'
201
202 alias h='history'
203 alias j='jobs -l'
204 alias r='rlogin'
205 alias which='type -all'
206 alias ..='cd ..'
207 alias path='echo -e ${PATH//:/\\n}'
208 alias print='/usr/bin/lp -o nobanner -d $LPDEST' # Assumes LPDEST is defined
209 alias pjet='enscript -h -G -fCourier9 -d $LPDEST' # Pretty-print using enscript
210 alias background='xv -root -quit -max -rmode 5' # Put a picture in the background
211 alias du='du -kh'
212 alias df='df -kTh'
213
214 # The 'ls' family (this assumes you use the GNU ls)
215 alias la='ls -Al' # show hidden files
216 alias ls='ls -hF --color' # add colors for filetype recognition
217 alias lx='ls -lXB' # sort by extension
218 alias lk='ls -lSr' # sort by size
219 alias lc='ls -lcr' # sort by change time
220 alias lu='ls -lur' # sort by access time
221 alias lr='ls -lR' # recursive ls
222 alias lt='ls -ltr' # sort by date
223 alias lm='ls -al |more' # pipe through 'more'
224 alias tree='tree -Csu' # nice alternative to 'ls'
225
226 # tailoring 'less'
227 alias more='less'
228 export PAGER=less
229 export LESSCHARSET='latin1'
230 export LESSOPEN='|/usr/bin/lesspipe.sh %s 2>&-' # Use this if lesspipe.sh exists
231 export LESS='-i -N -w -z-4 -g -e -M -X -F -R -P%t?f%f \
232 :stdin .?pb%pb\%:?lbLine %lb:?bbByte %bb:-...'
233
234 # spelling typos - highly personnal :-)
235 alias xs='cd'
236 alias vf='cd'
237 alias moer='more'
238 alias moew='more'
239 alias kk='ll'
240
241 #----------------
242 # a few fun ones
243 #----------------
244
245 function xtitle ()
246 {
247 case "$TERM" in
248 *term | rxvt)
249 echo -n -e "\033]0;$*\007" ;;
250 *)
251 ;;
252 esac
253 }
254
255 # aliases...
256 alias top='xtitle Processes on $HOST && top'
257 alias make='xtitle Making $(basename $PWD) ; make'
258 alias ncftp="xtitle ncFTP ; ncftp"
259
260 # .. and functions
261 function man ()
262 {
263 for i ; do
264 xtitle The $(basename $1|tr -d .[:digit:]) manual
265 command man -F -a "$i"
266 done
267 }
268
269 function ll(){ ls -l "$@"| egrep "^d" ; ls -lXB "$@" 2>&-| egrep -v "^d|total "; }
270 function te() # wrapper around xemacs/gnuserv
271 {
272 if [ "$(gnuclient -batch -eval t 2>&-)" == "t" ]; then
273 gnuclient -q "$@";
274 else
275 ( xemacs "$@" &);
276 fi
277 }
278
279 #-----------------------------------
280 # File & strings related functions:
281 #-----------------------------------
282
283 # Find a file with a pattern in name:
284 function ff() { find . -type f -iname '*'$*'*' -ls ; }
285 # Find a file with pattern $1 in name and Execute $2 on it:
286 function fe() { find . -type f -iname '*'$1'*' -exec "${2:-file}" {} \; ; }
287 # find pattern in a set of filesand highlight them:
288 function fstr()
289 {
290 OPTIND=1
291 local case=""
292 local usage="fstr: find string in files.
293 Usage: fstr [-i] \"pattern\" [\"filename pattern\"] "
294 while getopts :it opt
295 do
296 case "$opt" in
297 i) case="-i " ;;
298 *) echo "$usage"; return;;
299 esac
300 done
301 shift $(( $OPTIND - 1 ))
302 if [ "$#" -lt 1 ]; then
303 echo "$usage"
304 return;
305 fi
306 local SMSO=$(tput smso)
307 local RMSO=$(tput rmso)
308 find . -type f -name "${2:-*}" -print0 | xargs -0 grep -sn ${case} "$1" 2>&- | \
309 sed "s/$1/${SMSO}\0${RMSO}/gI" | more
310 }
311
312 function cuttail() # cut last n lines in file, 10 by default
313 {
314 nlines=${2:-10}
315 sed -n -e :a -e "1,${nlines}!{P;N;D;};N;ba" $1
316 }
317
318 function lowercase() # move filenames to lowercase
319 {
320 for file ; do
321 filename=${file##*/}
322 case "$filename" in
323 */*) dirname==${file%/*} ;;
324 *) dirname=.;;
325 esac
326 nf=$(echo $filename | tr A-Z a-z)
327 newname="${dirname}/${nf}"
328 if [ "$nf" != "$filename" ]; then
329 mv "$file" "$newname"
330 echo "lowercase: $file --> $newname"
331 else
332 echo "lowercase: $file not changed."
333 fi
334 done
335 }
336
337 function swap() # swap 2 filenames around
338 {
339 local TMPFILE=tmp.$$
340 mv "$1" $TMPFILE
341 mv "$2" "$1"
342 mv $TMPFILE "$2"
343 }
344
345
346 #-----------------------------------
347 # Process/system related functions:
348 #-----------------------------------
349
350 function my_ps() { ps $@ -u $USER -o pid,%cpu,%mem,bsdtime,command ; }
351 function pp() { my_ps f | awk '!/awk/ && $0~var' var=${1:-".*"} ; }
352
353 # This function is roughly the same as 'killall' on linux
354 # but has no equivalent (that I know of) on Solaris
355 function killps() # kill by process name
356 {
357 local pid pname sig="-TERM" # default signal
358 if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then
359 echo "Usage: killps [-SIGNAL] pattern"
360 return;
361 fi
362 if [ $# = 2 ]; then sig=$1 ; fi
363 for pid in $(my_ps| awk '!/awk/ && $0~pat { print $1 }' pat=${!#} ) ; do
364 pname=$(my_ps | awk '$1~var { print $5 }' var=$pid )
365 if ask "Kill process $pid <$pname> with signal $sig?"
366 then kill $sig $pid
367 fi
368 done
369 }
370
371 function my_ip() # get IP adresses
372 {
373 MY_IP=$(/sbin/ifconfig ppp0 | awk '/inet/ { print $2 } ' | sed -e s/addr://)
374 MY_ISP=$(/sbin/ifconfig ppp0 | awk '/P-t-P/ { print $3 } ' | sed -e s/P-t-P://)
375 }
376
377 function ii() # get current host related info
378 {
379 echo -e "\nYou are logged on ${RED}$HOST"
380 echo -e "\nAdditionnal information:$NC " ; uname -a
381 echo -e "\n${RED}Users logged on:$NC " ; w -h
382 echo -e "\n${RED}Current date :$NC " ; date
383 echo -e "\n${RED}Machine stats :$NC " ; uptime
384 echo -e "\n${RED}Memory stats :$NC " ; free
385 my_ip 2>&- ;
386 echo -e "\n${RED}Local IP Address :$NC" ; echo ${MY_IP:-"Not connected"}
387 echo -e "\n${RED}ISP Address :$NC" ; echo ${MY_ISP:-"Not connected"}
388 echo
389 }
390
391 # Misc utilities:
392
393 function repeat() # repeat n times command
394 {
395 local i max
396 max=$1; shift;
397 for ((i=1; i <= max ; i++)); do # --> C-like syntax
398 eval "$@";
399 done
400 }
401
402 function ask()
403 {
404 echo -n "$@" '[y/n] ' ; read ans
405 case "$ans" in
406 y*|Y*) return 0 ;;
407 *) return 1 ;;
408 esac
409 }
410
411 #=========================================================================
412 #
413 # PROGRAMMABLE COMPLETION - ONLY SINCE BASH-2.04
414 # Most are taken from the bash 2.05 documentation and from Ian McDonalds
415 # 'Bash completion' package (http://www.caliban.org/bash/index.shtml#completion)
416 # You will in fact need bash-2.05a for some features
417 #
418 #=========================================================================
419
420 if [ "${BASH_VERSION%.*}" \< "2.05" ]; then
421 echo "You will need to upgrade to version 2.05 for programmable completion"
422 return
423 fi
424
425 shopt -s extglob # necessary
426 set +o nounset # otherwise some completions will fail
427
428 complete -A hostname rsh rcp telnet rlogin r ftp ping disk
429 complete -A export printenv
430 complete -A variable export local readonly unset
431 complete -A enabled builtin
432 complete -A alias alias unalias
433 complete -A function function
434 complete -A user su mail finger
435
436 complete -A helptopic help # currently same as builtins
437 complete -A shopt shopt
438 complete -A stopped -P '%' bg
439 complete -A job -P '%' fg jobs disown
440
441 complete -A directory mkdir rmdir
442 complete -A directory -o default cd
443
444 # Compression
445 complete -f -o default -X '*.+(zip|ZIP)' zip
446 complete -f -o default -X '!*.+(zip|ZIP)' unzip
447 complete -f -o default -X '*.+(z|Z)' compress
448 complete -f -o default -X '!*.+(z|Z)' uncompress
449 complete -f -o default -X '*.+(gz|GZ)' gzip
450 complete -f -o default -X '!*.+(gz|GZ)' gunzip
451 complete -f -o default -X '*.+(bz2|BZ2)' bzip2
452 complete -f -o default -X '!*.+(bz2|BZ2)' bunzip2
453 # Postscript,pdf,dvi.....
454 complete -f -o default -X '!*.ps' gs ghostview ps2pdf ps2ascii
455 complete -f -o default -X '!*.dvi' dvips dvipdf xdvi dviselect dvitype
456 complete -f -o default -X '!*.pdf' acroread pdf2ps
457 complete -f -o default -X '!*.+(pdf|ps)' gv
458 complete -f -o default -X '!*.texi*' makeinfo texi2dvi texi2html texi2pdf
459 complete -f -o default -X '!*.tex' tex latex slitex
460 complete -f -o default -X '!*.lyx' lyx
461 complete -f -o default -X '!*.+(htm*|HTM*)' lynx html2ps
462 # Multimedia
463 complete -f -o default -X '!*.+(jp*g|gif|xpm|png|bmp)' xv gimp
464 complete -f -o default -X '!*.+(mp3|MP3)' mpg123 mpg321
465 complete -f -o default -X '!*.+(ogg|OGG)' ogg123
466
467
468
469 complete -f -o default -X '!*.pl' perl perl5
470
471 # This is a 'universal' completion function - it works when commands have
472 # a so-called 'long options' mode , ie: 'ls --all' instead of 'ls -a'
473
474 _get_longopts ()
475 {
476 $1 --help | sed -e '/--/!d' -e 's/.*--\([^[:space:].,]*\).*/--\1/'| \
477 grep ^"$2" |sort -u ;
478 }
479
480 _longopts_func ()
481 {
482 case "${2:-*}" in
483 -*) ;;
484 *) return ;;
485 esac
486
487 case "$1" in
488 \~*) eval cmd="$1" ;;
489 *) cmd="$1" ;;
490 esac
491 COMPREPLY=( $(_get_longopts ${1} ${2} ) )
492 }
493 complete -o default -F _longopts_func configure bash
494 complete -o default -F _longopts_func wget id info a2ps ls recode
495
496
497 _make_targets ()
498 {
499 local mdef makef gcmd cur prev i
500
501 COMPREPLY=()
502 cur=${COMP_WORDS[COMP_CWORD]}
503 prev=${COMP_WORDS[COMP_CWORD-1]}
504
505 # if prev argument is -f, return possible filename completions.
506 # we could be a little smarter here and return matches against
507 # `makefile Makefile *.mk', whatever exists
508 case "$prev" in
509 -*f) COMPREPLY=( $(compgen -f $cur ) ); return 0;;
510 esac
511
512 # if we want an option, return the possible posix options
513 case "$cur" in
514 -) COMPREPLY=(-e -f -i -k -n -p -q -r -S -s -t); return 0;;
515 esac
516
517 # make reads `makefile' before `Makefile'
518 if [ -f makefile ]; then
519 mdef=makefile
520 elif [ -f Makefile ]; then
521 mdef=Makefile
522 else
523 mdef=*.mk # local convention
524 fi
525
526 # before we scan for targets, see if a makefile name was specified
527 # with -f
528 for (( i=0; i < ${#COMP_WORDS[@]}; i++ )); do
529 if [[ ${COMP_WORDS[i]} == -*f ]]; then
530 eval makef=${COMP_WORDS[i+1]} # eval for tilde expansion
531 break
532 fi
533 done
534
535 [ -z "$makef" ] && makef=$mdef
536
537 # if we have a partial word to complete, restrict completions to
538 # matches of that word
539 if [ -n "$2" ]; then gcmd='grep "^$2"' ; else gcmd=cat ; fi
540
541 # if we don't want to use *.mk, we can take out the cat and use
542 # test -f $makef and input redirection
543 COMPREPLY=( $(cat $makef 2>/dev/null | awk 'BEGIN {FS=":"} /^[^.# ][^=]*:/ {print $1}' | tr -s ' ' '\012' | sort -u | eval $gcmd ) )
544 }
545
546 complete -F _make_targets -X '+($*|*.[cho])' make gmake pmake
547
548
549 # cvs(1) completion
550 _cvs ()
551 {
552 local cur prev
553 COMPREPLY=()
554 cur=${COMP_WORDS[COMP_CWORD]}
555 prev=${COMP_WORDS[COMP_CWORD-1]}
556
557 if [ $COMP_CWORD -eq 1 ] || [ "${prev:0:1}" = "-" ]; then
558 COMPREPLY=( $( compgen -W 'add admin checkout commit diff \
559 export history import log rdiff release remove rtag status \
560 tag update' $cur ))
561 else
562 COMPREPLY=( $( compgen -f $cur ))
563 fi
564 return 0
565 }
566 complete -F _cvs cvs
567
568 _killall ()
569 {
570 local cur prev
571 COMPREPLY=()
572 cur=${COMP_WORDS[COMP_CWORD]}
573
574 # get a list of processes (the first sed evaluation
575 # takes care of swapped out processes, the second
576 # takes care of getting the basename of the process)
577 COMPREPLY=( $( /usr/bin/ps -u $USER -o comm | \
578 sed -e '1,1d' -e 's#[]\[]##g' -e 's#^.*/##'| \
579 awk '{if ($0 ~ /^'$cur'/) print $0}' ))
580
581 return 0
582 }
583
584 complete -F _killall killall killps
585
586
587 # A meta-command completion function for commands like sudo(8), which need to
588 # first complete on a command, then complete according to that command's own
589 # completion definition - currently not quite foolproof (e.g. mount and umount
590 # don't work properly), but still quite useful - By Ian McDonald, modified by me.
591
592 _my_command()
593 {
594 local cur func cline cspec
595
596 COMPREPLY=()
597 cur=${COMP_WORDS[COMP_CWORD]}
598
599 if [ $COMP_CWORD = 1 ]; then
600 COMPREPLY=( $( compgen -c $cur ) )
601 elif complete -p ${COMP_WORDS[1]} &>/dev/null; then
602 cspec=$( complete -p ${COMP_WORDS[1]} )
603 if [ "${cspec%%-F *}" != "${cspec}" ]; then
604 # complete -F <function>
605 #
606 # COMP_CWORD and COMP_WORDS() are not read-only,
607 # so we can set them before handing off to regular
608 # completion routine
609
610 # set current token number to 1 less than now
611 COMP_CWORD=$(( $COMP_CWORD - 1 ))
612 # get function name
613 func=${cspec#*-F }
614 func=${func%% *}
615 # get current command line minus initial command
616 cline="${COMP_LINE#$1 }"
617 # split current command line tokens into array
618 COMP_WORDS=( $cline )
619 $func $cline
620 elif [ "${cspec#*-[abcdefgjkvu]}" != "" ]; then
621 # complete -[abcdefgjkvu]
622 #func=$( echo $cspec | sed -e 's/^.*\(-[abcdefgjkvu]\).*$/\1/' )
623 func=$( echo $cspec | sed -e 's/^complete//' -e 's/[^ ]*$//' )
624 COMPREPLY=( $( eval compgen $func $cur ) )
625 elif [ "${cspec#*-A}" != "$cspec" ]; then
626 # complete -A <type>
627 func=${cspec#*-A }
628 func=${func%% *}
629 COMPREPLY=( $( compgen -A $func $cur ) )
630 fi
631 else
632 COMPREPLY=( $( compgen -f $cur ) )
633 fi
634 }
635
636
637 complete -o default -F _my_command nohup exec eval trace truss strace sotruss gdb
638 complete -o default -F _my_command command type which man nice
639
640 # Local Variables:
641 # mode:shell-script
642 # sh-shell:bash
643 # End: |