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