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 L-1. Sample .bashrc file
1 #=============================================================
2 #
3 # PERSONAL $HOME/.bashrc FILE for bash-3.0 (or later)
4 # By Emmanuel Rouat <no-email>
5 #
6 # Last modified: Sun Nov 30 16:27:45 CET 2008
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 # The majority of the code here assumes you are on a GNU
12 # system (most likely a Linux box) and is based on code found
13 # on Usenet or internet. See for instance:
14 #
15 # http://tldp.org/LDP/abs/html/index.html
16 # http://www.caliban.org/bash/
17 # http://www.shelldorado.com/scripts/categories.html
18 # http://www.dotfiles.org/
19 #
20 # This bashrc file is a bit overcrowded -- remember it is just
21 # just an example. Tailor it to your needs.
22 #
23 #
24 #=============================================================
25
26 # --> Comments added by HOWTO author.
27
28
29 #-------------------------------------------------------------
30 # Source global definitions (if any)
31 #-------------------------------------------------------------
32
33
34 if [ -f /etc/bashrc ]; then
35 . /etc/bashrc # --> Read /etc/bashrc, if present.
36 fi
37
38 #-------------------------------------------------------------
39 # Automatic setting of $DISPLAY (if not set already).
40 # This works for linux - your mileage may vary. ...
41 # The problem is that different types of terminals give
42 # different answers to 'who am i' (rxvt in particular can be
43 # troublesome).
44 # I have not found a 'universal' method yet.
45 #-------------------------------------------------------------
46
47 function get_xserver ()
48 {
49 case $TERM in
50 xterm )
51 XSERVER=$(who am i | awk '{print $NF}' | tr -d ')''(' )
52 # Ane-Pieter Wieringa suggests the following alternative:
53 # I_AM=$(who am i)
54 # SERVER=${I_AM#*(}
55 # SERVER=${SERVER%*)}
56
57 XSERVER=${XSERVER%%:*}
58 ;;
59 aterm | rxvt)
60 # Find some code that works here. ...
61 ;;
62 esac
63 }
64
65 if [ -z ${DISPLAY:=""} ]; then
66 get_xserver
67 if [[ -z ${XSERVER} || ${XSERVER} == $(hostname) || \
68 ${XSERVER} == "unix" ]]; then
69 DISPLAY=":0.0" # Display on local host.
70 else
71 DISPLAY=${XSERVER}:0.0 # Display on remote host.
72 fi
73 fi
74
75 export DISPLAY
76
77 #-------------------------------------------------------------
78 # Some settings
79 #-------------------------------------------------------------
80
81 ulimit -S -c 0 # Don't want any coredumps.
82 set -o notify
83 set -o noclobber
84 set -o ignoreeof
85 set -o nounset
86 #set -o xtrace # Useful for debuging.
87
88 # Enable options:
89 shopt -s cdspell
90 shopt -s cdable_vars
91 shopt -s checkhash
92 shopt -s checkwinsize
93 shopt -s sourcepath
94 shopt -s no_empty_cmd_completion
95 shopt -s cmdhist
96 shopt -s histappend histreedit histverify
97 shopt -s extglob # Necessary for programmable completion.
98
99 # Disable options:
100 shopt -u mailwarn
101 unset MAILCHECK # Don't want my shell to warn me of incoming mail.
102
103
104 export TIMEFORMAT=$'\nreal %3R\tuser %3U\tsys %3S\tpcpu %P\n'
105 export HISTTIMEFORMAT="%H:%M > "
106 export HISTIGNORE="&:bg:fg:ll:h"
107 export HOSTFILE=$HOME/.hosts # Put list of remote hosts in ~/.hosts ...
108
109
110
111 #-------------------------------------------------------------
112 # Greeting, motd etc...
113 #-------------------------------------------------------------
114
115 # Define some colors first:
116 red='\e[0;31m'
117 RED='\e[1;31m'
118 blue='\e[0;34m'
119 BLUE='\e[1;34m'
120 cyan='\e[0;36m'
121 CYAN='\e[1;36m'
122 NC='\e[0m' # No Color
123 # --> Nice. Has the same effect as using "ansi.sys" in DOS.
124
125
126 # Looks best on a terminal with black background.....
127 echo -e "${CYAN}This is BASH ${RED}${BASH_VERSION%.*}\
128 ${CYAN} - DISPLAY on ${RED}$DISPLAY${NC}\n"
129 date
130 if [ -x /usr/games/fortune ]; then
131 /usr/games/fortune -s # Makes our day a bit more fun.... :-)
132 fi
133
134 function _exit() # Function to run upon exit of shell.
135 {
136 echo -e "${RED}Hasta la vista, baby${NC}"
137 }
138 trap _exit EXIT
139
140
141 #-------------------------------------------------------------
142 # Shell Prompt
143 #-------------------------------------------------------------
144
145
146 if [[ "${DISPLAY%%:0*}" != "" ]]; then
147 HILIT=${red} # remote machine: prompt will be partly red
148 else
149 HILIT=${cyan} # local machine: prompt will be partly cyan
150 fi
151
152 # --> Replace instances of \W with \w in prompt functions below
153 #+ --> to get display of full path name.
154
155 function fastprompt()
156 {
157 unset PROMPT_COMMAND
158 case $TERM in
159 *term | rxvt )
160 PS1="${HILIT}[\h]$NC \W > \[\033]0;\${TERM} [\u@\h] \w\007\]" ;;
161 linux )
162 PS1="${HILIT}[\h]$NC \W > " ;;
163 *)
164 PS1="[\h] \W > " ;;
165 esac
166 }
167
168
169 _powerprompt()
170 {
171 LOAD=$(uptime|sed -e "s/.*: \([^,]*\).*/\1/" -e "s/ //g")
172 }
173
174 function powerprompt()
175 {
176
177 PROMPT_COMMAND=_powerprompt
178 case $TERM in
179 *term | rxvt )
180 PS1="${HILIT}[\A - \$LOAD]$NC\n[\u@\h \#] \W > \
181 \[\033]0;\${TERM} [\u@\h] \w\007\]" ;;
182 linux )
183 PS1="${HILIT}[\A - \$LOAD]$NC\n[\u@\h \#] \W > " ;;
184 * )
185 PS1="[\A - \$LOAD]\n[\u@\h \#] \W > " ;;
186 esac
187 }
188
189 powerprompt # This is the default prompt -- might be slow.
190 # If too slow, use fastprompt instead. ...
191
192 #===============================================================
193 #
194 # ALIASES AND FUNCTIONS
195 #
196 # Arguably, some functions defined here are quite big.
197 # If you want to make this file smaller, these functions can
198 # be converted into scripts and removed from here.
199 #
200 # Many functions were taken (almost) straight from the bash-2.04
201 # examples.
202 #
203 #===============================================================
204
205 #-------------------
206 # Personnal Aliases
207 #-------------------
208
209 alias rm='rm -i'
210 alias cp='cp -i'
211 alias mv='mv -i'
212 # -> Prevents accidentally clobbering files.
213 alias mkdir='mkdir -p'
214
215 alias h='history'
216 alias j='jobs -l'
217 alias which='type -a'
218 alias ..='cd ..'
219 alias path='echo -e ${PATH//:/\\n}'
220 alias libpath='echo -e ${LD_LIBRARY_PATH//:/\\n}'
221 alias print='/usr/bin/lp -o nobanner -d $LPDEST'
222 # Assumes LPDEST is defined (default printer)
223 alias pjet='enscript -h -G -fCourier9 -d $LPDEST'
224 # Pretty-print using enscript
225
226 alias du='du -kh' # Makes a more readable output.
227 alias df='df -kTh'
228
229 #-------------------------------------------------------------
230 # The 'ls' family (this assumes you use a recent GNU ls)
231 #-------------------------------------------------------------
232 alias ll="ls -l --group-directories-first"
233 alias ls='ls -hF --color' # add colors for filetype recognition
234 alias la='ls -Al' # show hidden files
235 alias lx='ls -lXB' # sort by extension
236 alias lk='ls -lSr' # sort by size, biggest last
237 alias lc='ls -ltcr' # sort by and show change time, most recent last
238 alias lu='ls -ltur' # sort by and show access time, most recent last
239 alias lt='ls -ltr' # sort by date, most recent last
240 alias lm='ls -al |more' # pipe through 'more'
241 alias lr='ls -lR' # recursive ls
242 alias tree='tree -Csu' # nice alternative to 'recursive ls'
243
244 # If your version of 'ls' doesn't support --group-directories-first try this:
245 # function ll(){ ls -l "$@"| egrep "^d" ; ls -lXB "$@" 2>&-| \
246 # egrep -v "^d|total "; }
247
248
249 #-------------------------------------------------------------
250 # tailoring 'less'
251 #-------------------------------------------------------------
252
253 alias more='less'
254 export PAGER=less
255 export LESSCHARSET='latin1'
256 export LESSOPEN='|/usr/bin/lesspipe.sh %s 2>&-'
257 # Use this if lesspipe.sh exists
258 export LESS='-i -N -w -z-4 -g -e -M -X -F -R -P%t?f%f \
259 :stdin .?pb%pb\%:?lbLine %lb:?bbByte %bb:-...'
260
261
262 #-------------------------------------------------------------
263 # spelling typos - highly personnal and keyboard-dependent :-)
264 #-------------------------------------------------------------
265
266 alias xs='cd'
267 alias vf='cd'
268 alias moer='more'
269 alias moew='more'
270 alias kk='ll'
271
272
273 #-------------------------------------------------------------
274 # A few fun ones
275 #-------------------------------------------------------------
276
277
278 function xtitle() # Adds some text in the terminal frame.
279 {
280 case "$TERM" in
281 *term | rxvt)
282 echo -n -e "\033]0;$*\007" ;;
283 *)
284 ;;
285 esac
286 }
287
288 # aliases that use xtitle
289 alias top='xtitle Processes on $HOST && top'
290 alias make='xtitle Making $(basename $PWD) ; make'
291 alias ncftp="xtitle ncFTP ; ncftp"
292
293 # .. and functions
294 function man()
295 {
296 for i ; do
297 xtitle The $(basename $1|tr -d .[:digit:]) manual
298 command man -F -a "$i"
299 done
300 }
301
302
303 #-------------------------------------------------------------
304 # Make the following commands run in background automatically:
305 #-------------------------------------------------------------
306
307 function te() # Wrapper around xemacs/gnuserv ...
308 {
309 if [ "$(gnuclient -batch -eval t 2>&-)" == "t" ]; then
310 gnuclient -q "$@";
311 else
312 ( xemacs "$@" &);
313 fi
314 }
315
316 function soffice() { command soffice "$@" & }
317 function firefox() { command firefox "$@" & }
318 function xpdf() { command xpdf "$@" & }
319
320
321 #-------------------------------------------------------------
322 # File & string-related functions:
323 #-------------------------------------------------------------
324
325
326 # Find a file with a pattern in name:
327 function ff() { find . -type f -iname '*'$*'*' -ls ; }
328
329 # Find a file with pattern $1 in name and Execute $2 on it:
330 function fe()
331 { find . -type f -iname '*'${1:-}'*' -exec ${2:-file} {} \; ; }
332
333 # Find a pattern in a set of files and highlight them:
334 # (needs a recent version of egrep)
335 function fstr()
336 {
337 OPTIND=1
338 local case=""
339 local usage="fstr: find string in files.
340 Usage: fstr [-i] \"pattern\" [\"filename pattern\"] "
341 while getopts :it opt
342 do
343 case "$opt" in
344 i) case="-i " ;;
345 *) echo "$usage"; return;;
346 esac
347 done
348 shift $(( $OPTIND - 1 ))
349 if [ "$#" -lt 1 ]; then
350 echo "$usage"
351 return;
352 fi
353 find . -type f -name "${2:-*}" -print0 | \
354 xargs -0 egrep --color=always -sn ${case} "$1" 2>&- | more
355
356 }
357
358 function cuttail() # cut last n lines in file, 10 by default
359 {
360 nlines=${2:-10}
361 sed -n -e :a -e "1,${nlines}!{P;N;D;};N;ba" $1
362 }
363
364 function lowercase() # move filenames to lowercase
365 {
366 for file ; do
367 filename=${file##*/}
368 case "$filename" in
369 */*) dirname==${file%/*} ;;
370 *) dirname=.;;
371 esac
372 nf=$(echo $filename | tr A-Z a-z)
373 newname="${dirname}/${nf}"
374 if [ "$nf" != "$filename" ]; then
375 mv "$file" "$newname"
376 echo "lowercase: $file --> $newname"
377 else
378 echo "lowercase: $file not changed."
379 fi
380 done
381 }
382
383
384 function swap() # Swap 2 filenames around, if they exist
385 { #(from Uzi's bashrc).
386 local TMPFILE=tmp.$$
387
388 [ $# -ne 2 ] && echo "swap: 2 arguments needed" && return 1
389 [ ! -e $1 ] && echo "swap: $1 does not exist" && return 1
390 [ ! -e $2 ] && echo "swap: $2 does not exist" && return 1
391
392 mv "$1" $TMPFILE
393 mv "$2" "$1"
394 mv $TMPFILE "$2"
395 }
396
397 function extract() # Handy Extract Program.
398 {
399 if [ -f $1 ] ; then
400 case $1 in
401 *.tar.bz2) tar xvjf $1 ;;
402 *.tar.gz) tar xvzf $1 ;;
403 *.bz2) bunzip2 $1 ;;
404 *.rar) unrar x $1 ;;
405 *.gz) gunzip $1 ;;
406 *.tar) tar xvf $1 ;;
407 *.tbz2) tar xvjf $1 ;;
408 *.tgz) tar xvzf $1 ;;
409 *.zip) unzip $1 ;;
410 *.Z) uncompress $1 ;;
411 *.7z) 7z x $1 ;;
412 *) echo "'$1' cannot be extracted via >extract<" ;;
413 esac
414 else
415 echo "'$1' is not a valid file"
416 fi
417 }
418
419 #-------------------------------------------------------------
420 # Process/system related functions:
421 #-------------------------------------------------------------
422
423
424 function my_ps() { ps $@ -u $USER -o pid,%cpu,%mem,bsdtime,command ; }
425 function pp() { my_ps f | awk '!/awk/ && $0~var' var=${1:-".*"} ; }
426
427
428 function killps() # Kill by process name.
429 {
430 local pid pname sig="-TERM" # Default signal.
431 if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then
432 echo "Usage: killps [-SIGNAL] pattern"
433 return;
434 fi
435 if [ $# = 2 ]; then sig=$1 ; fi
436 for pid in $(my_ps| awk '!/awk/ && $0~pat { print $1 }' pat=${!#} ) ; do
437 pname=$(my_ps | awk '$1~var { print $5 }' var=$pid )
438 if ask "Kill process $pid <$pname> with signal $sig?"
439 then kill $sig $pid
440 fi
441 done
442 }
443
444 function my_ip() # Get IP adresses.
445 {
446 MY_IP=$(/sbin/ifconfig ppp0 | awk '/inet/ { print $2 } ' | \
447 sed -e s/addr://)
448 MY_ISP=$(/sbin/ifconfig ppp0 | awk '/P-t-P/ { print $3 } ' | \
449 sed -e s/P-t-P://)
450 }
451
452 function ii() # Get current host related info.
453 {
454 echo -e "\nYou are logged on ${RED}$HOST"
455 echo -e "\nAdditionnal information:$NC " ; uname -a
456 echo -e "\n${RED}Users logged on:$NC " ; w -h
457 echo -e "\n${RED}Current date :$NC " ; date
458 echo -e "\n${RED}Machine stats :$NC " ; uptime
459 echo -e "\n${RED}Memory stats :$NC " ; free
460 my_ip 2>&- ;
461 echo -e "\n${RED}Local IP Address :$NC" ; echo ${MY_IP:-"Not connected"}
462 echo -e "\n${RED}ISP Address :$NC" ; echo ${MY_ISP:-"Not connected"}
463 echo -e "\n${RED}Open connections :$NC "; netstat -pan --inet;
464 echo
465 }
466
467 #-------------------------------------------------------------
468 # Misc utilities:
469 #-------------------------------------------------------------
470
471 function repeat() # Repeat n times command.
472 {
473 local i max
474 max=$1; shift;
475 for ((i=1; i <= max ; i++)); do # --> C-like syntax
476 eval "$@";
477 done
478 }
479
480
481 function ask() # See 'killps' for example of use.
482 {
483 echo -n "$@" '[y/n] ' ; read ans
484 case "$ans" in
485 y*|Y*) return 0 ;;
486 *) return 1 ;;
487 esac
488 }
489
490 function corename() # Get name of app that created a corefile.
491 {
492 for file ; do
493 echo -n $file : ; gdb --core=$file --batch | head -1
494 done
495 }
496
497
498
499
500 #=========================================================================
501 # PROGRAMMABLE COMPLETION - ONLY SINCE BASH-2.04
502 # Most are taken from the bash 2.05 documentation and from Ian McDonald's
503 # 'Bash completion' package (http://www.caliban.org/bash/#completion).
504 # You will in fact need bash more recent than 3.0 for some features.
505 #=========================================================================
506
507 if [ "${BASH_VERSION%.*}" \< "3.0" ]; then
508 echo "You will need to upgrade to version 3.0 \
509 for full programmable completion features."
510 return
511 fi
512
513 shopt -s extglob # Necessary,
514 #set +o nounset # otherwise some completions will fail.
515
516 complete -A hostname rsh rcp telnet rlogin r ftp ping disk
517 complete -A export printenv
518 complete -A variable export local readonly unset
519 complete -A enabled builtin
520 complete -A alias alias unalias
521 complete -A function function
522 complete -A user su mail finger
523
524 complete -A helptopic help # Currently, same as builtins.
525 complete -A shopt shopt
526 complete -A stopped -P '%' bg
527 complete -A job -P '%' fg jobs disown
528
529 complete -A directory mkdir rmdir
530 complete -A directory -o default cd
531
532 # Compression
533 complete -f -o default -X '*.+(zip|ZIP)' zip
534 complete -f -o default -X '!*.+(zip|ZIP)' unzip
535 complete -f -o default -X '*.+(z|Z)' compress
536 complete -f -o default -X '!*.+(z|Z)' uncompress
537 complete -f -o default -X '*.+(gz|GZ)' gzip
538 complete -f -o default -X '!*.+(gz|GZ)' gunzip
539 complete -f -o default -X '*.+(bz2|BZ2)' bzip2
540 complete -f -o default -X '!*.+(bz2|BZ2)' bunzip2
541 complete -f -o default -X '!*.+(zip|ZIP|z|Z|gz|GZ|bz2|BZ2)' extract
542
543
544 # Documents - Postscript,pdf,dvi.....
545 complete -f -o default -X '!*.+(ps|PS)' gs ghostview ps2pdf ps2ascii
546 complete -f -o default -X '!*.+(dvi|DVI)' dvips dvipdf xdvi dviselect dvitype
547 complete -f -o default -X '!*.+(pdf|PDF)' acroread pdf2ps
548 complete -f -o default -X \
549 '!*.@(@(?(e)ps|?(E)PS|pdf|PDF)?(.gz|.GZ|.bz2|.BZ2|.Z))' gv ggv
550 complete -f -o default -X '!*.texi*' makeinfo texi2dvi texi2html texi2pdf
551 complete -f -o default -X '!*.tex' tex latex slitex
552 complete -f -o default -X '!*.lyx' lyx
553 complete -f -o default -X '!*.+(htm*|HTM*)' lynx html2ps
554 complete -f -o default -X \
555 '!*.+(doc|DOC|xls|XLS|ppt|PPT|sx?|SX?|csv|CSV|od?|OD?|ott|OTT)' soffice
556
557 # Multimedia
558 complete -f -o default -X \
559 '!*.+(gif|GIF|jp*g|JP*G|bmp|BMP|xpm|XPM|png|PNG)' xv gimp ee gqview
560 complete -f -o default -X '!*.+(mp3|MP3)' mpg123 mpg321
561 complete -f -o default -X '!*.+(ogg|OGG)' ogg123
562 complete -f -o default -X \
563 '!*.@(mp[23]|MP[23]|ogg|OGG|wav|WAV|pls|m3u|xm|mod|s[3t]m|it|mtm|ult|flac)' xmms
564 complete -f -o default -X \
565 '!*.@(mp?(e)g|MP?(E)G|wma|avi|AVI|asf|vob|VOB|bin|dat|vcd|\
566 ps|pes|fli|viv|rm|ram|yuv|mov|MOV|qt|QT|wmv|mp3|MP3|ogg|OGG|\
567 ogm|OGM|mp4|MP4|wav|WAV|asx|ASX)' xine
568
569
570
571 complete -f -o default -X '!*.pl' perl perl5
572
573
574 # This is a 'universal' completion function - it works when commands have
575 # a so-called 'long options' mode , ie: 'ls --all' instead of 'ls -a'
576 # Needs the '-o' option of grep
577 # (try the commented-out version if not available).
578
579 # First, remove '=' from completion word separators
580 # (this will allow completions like 'ls --color=auto' to work correctly).
581
582 COMP_WORDBREAKS=${COMP_WORDBREAKS/=/}
583
584
585 _get_longopts()
586 {
587 #$1 --help | sed -e '/--/!d' -e 's/.*--\([^[:space:].,]*\).*/--\1/'| \
588 #grep ^"$2" |sort -u ;
589 $1 --help | grep -o -e "--[^[:space:].,]*" | grep -e "$2" |sort -u
590 }
591
592 _longopts()
593 {
594 local cur
595 cur=${COMP_WORDS[COMP_CWORD]}
596
597 case "${cur:-*}" in
598 -*) ;;
599 *) return ;;
600 esac
601
602 case "$1" in
603 \~*) eval cmd="$1" ;;
604 *) cmd="$1" ;;
605 esac
606 COMPREPLY=( $(_get_longopts ${1} ${cur} ) )
607 }
608 complete -o default -F _longopts configure bash
609 complete -o default -F _longopts wget id info a2ps ls recode
610
611 _tar()
612 {
613 local cur ext regex tar untar
614
615 COMPREPLY=()
616 cur=${COMP_WORDS[COMP_CWORD]}
617
618 # If we want an option, return the possible long options.
619 case "$cur" in
620 -*) COMPREPLY=( $(_get_longopts $1 $cur ) ); return 0;;
621 esac
622
623 if [ $COMP_CWORD -eq 1 ]; then
624 COMPREPLY=( $( compgen -W 'c t x u r d A' -- $cur ) )
625 return 0
626 fi
627
628 case "${COMP_WORDS[1]}" in
629 ?(-)c*f)
630 COMPREPLY=( $( compgen -f $cur ) )
631 return 0
632 ;;
633 +([^Izjy])f)
634 ext='tar'
635 regex=$ext
636 ;;
637 *z*f)
638 ext='tar.gz'
639 regex='t\(ar\.\)\(gz\|Z\)'
640 ;;
641 *[Ijy]*f)
642 ext='t?(ar.)bz?(2)'
643 regex='t\(ar\.\)bz2\?'
644 ;;
645 *)
646 COMPREPLY=( $( compgen -f $cur ) )
647 return 0
648 ;;
649
650 esac
651
652 if [[ "$COMP_LINE" == tar*.$ext' '* ]]; then
653 # Complete on files in tar file.
654 #
655 # Get name of tar file from command line.
656 tar=$( echo "$COMP_LINE" | \
657 sed -e 's|^.* \([^ ]*'$regex'\) .*$|\1|' )
658 # Devise how to untar and list it.
659 untar=t${COMP_WORDS[1]//[^Izjyf]/}
660
661 COMPREPLY=( $( compgen -W "$( echo $( tar $untar $tar \
662 2>/dev/null ) )" -- "$cur" ) )
663 return 0
664
665 else
666 # File completion on relevant files.
667 COMPREPLY=( $( compgen -G $cur\*.$ext ) )
668
669 fi
670
671 return 0
672
673 }
674
675 complete -F _tar -o default tar
676
677 _make()
678 {
679 local mdef makef makef_dir="." makef_inc gcmd cur prev i;
680 COMPREPLY=();
681 cur=${COMP_WORDS[COMP_CWORD]};
682 prev=${COMP_WORDS[COMP_CWORD-1]};
683 case "$prev" in
684 -*f)
685 COMPREPLY=($(compgen -f $cur ));
686 return 0
687 ;;
688 esac;
689 case "$cur" in
690 -*)
691 COMPREPLY=($(_get_longopts $1 $cur ));
692 return 0
693 ;;
694 esac;
695
696 # make reads `GNUmakefile', then `makefile', then `Makefile'
697 if [ -f ${makef_dir}/GNUmakefile ]; then
698 makef=${makef_dir}/GNUmakefile
699 elif [ -f ${makef_dir}/makefile ]; then
700 makef=${makef_dir}/makefile
701 elif [ -f ${makef_dir}/Makefile ]; then
702 makef=${makef_dir}/Makefile
703 else
704 makef=${makef_dir}/*.mk # Local convention.
705 fi
706
707
708 # Before we scan for targets, see if a Makefile name was
709 # specified with -f ...
710 for (( i=0; i < ${#COMP_WORDS[@]}; i++ )); do
711 if [[ ${COMP_WORDS[i]} == -f ]]; then
712 # eval for tilde expansion
713 eval makef=${COMP_WORDS[i+1]}
714 break
715 fi
716 done
717 [ ! -f $makef ] && return 0
718
719 # deal with included Makefiles
720 makef_inc=$( grep -E '^-?include' $makef | \
721 sed -e "s,^.* ,"$makef_dir"/," )
722 for file in $makef_inc; do
723 [ -f $file ] && makef="$makef $file"
724 done
725
726
727 # If we have a partial word to complete, restrict completions to
728 # matches of that word.
729 if [ -n "$cur" ]; then gcmd='grep "^$cur"' ; else gcmd=cat ; fi
730
731 COMPREPLY=( $( awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ \
732 {split($1,A,/ /);for(i in A)print A[i]}' \
733 $makef 2>/dev/null | eval $gcmd ))
734
735 }
736
737 complete -F _make -X '+($*|*.[cho])' make gmake pmake
738
739
740
741
742 _killall()
743 {
744 local cur prev
745 COMPREPLY=()
746 cur=${COMP_WORDS[COMP_CWORD]}
747
748 # get a list of processes (the first sed evaluation
749 # takes care of swapped out processes, the second
750 # takes care of getting the basename of the process)
751 COMPREPLY=( $( /usr/bin/ps -u $USER -o comm | \
752 sed -e '1,1d' -e 's#[]\[]##g' -e 's#^.*/##'| \
753 awk '{if ($0 ~ /^'$cur'/) print $0}' ))
754
755 return 0
756 }
757
758 complete -F _killall killall killps
759
760
761
762 # A meta-command completion function for commands like sudo(8), which need to
763 # first complete on a command, then complete according to that command's own
764 # completion definition - currently not quite foolproof,
765 # but still quite useful (By Ian McDonald, modified by me).
766
767
768 _meta_comp()
769 {
770 local cur func cline cspec
771
772 COMPREPLY=()
773 cur=${COMP_WORDS[COMP_CWORD]}
774 cmdline=${COMP_WORDS[@]}
775 if [ $COMP_CWORD = 1 ]; then
776 COMPREPLY=( $( compgen -c $cur ) )
777 else
778 cmd=${COMP_WORDS[1]} # Find command.
779 cspec=$( complete -p ${cmd} ) # Find spec of that command.
780
781 # COMP_CWORD and COMP_WORDS() are not read-only,
782 # so we can set them before handing off to regular
783 # completion routine:
784 # Get current command line minus initial command,
785 cline="${COMP_LINE#$1 }"
786 # split current command line tokens into array,
787 COMP_WORDS=( $cline )
788 # set current token number to 1 less than now.
789 COMP_CWORD=$(( $COMP_CWORD - 1 ))
790 # If current arg is empty, add it to COMP_WORDS array
791 # (otherwise that information will be lost).
792 if [ -z $cur ]; then COMP_WORDS[COMP_CWORD]="" ; fi
793
794 if [ "${cspec%%-F *}" != "${cspec}" ]; then
795 # if -F then get function:
796 func=${cspec#*-F }
797 func=${func%% *}
798 eval $func $cline # Evaluate it.
799 else
800 func=$( echo $cspec | sed -e 's/^complete//' -e 's/[^ ]*$//' )
801 COMPREPLY=( $( eval compgen $func $cur ) )
802 fi
803
804 fi
805
806 }
807
808
809 complete -o default -F _meta_comp nohup \
810 eval exec trace truss strace sotruss gdb
811 complete -o default -F _meta_comp command type which man nice time
812
813 # Local Variables:
814 # mode:shell-script
815 # sh-shell:bash
816 # End: |
And, here is a snippet from Andrzej Szelachowski's instructive .bash_profile file.
Example L-2. .bash_profile file
1 # From Andrzej Szelachowski's ~/.bash_profile:
2
3
4 # Note that a variable may require special treatment
5 #+ if it will be exported.
6
7 DARKGRAY='\e[1;30m'
8 LIGHTRED='\e[1;31m'
9 GREEN='\e[32m'
10 YELLOW='\e[1;33m'
11 LIGHTBLUE='\e[1;34m'
12 NC='\e[m'
13
14 PCT="\`if [[ \$EUID -eq 0 ]]; then T='$LIGHTRED' ; else T='$LIGHTBLUE'; fi;
15 echo \$T \`"
16
17 # For "literal" command substitution to be assigned to a variable,
18 #+ use escapes and double quotes:
19 #+ PCT="\` ... \`" . . .
20 # Otherwise, the value of PCT variable is assigned only once,
21 #+ when the variable is exported/read from .bash_profile,
22 #+ and it will not change afterwards even if the user ID changes.
23
24
25 PS1="\n$GREEN[\w] \n$DARKGRAY($PCT\t$DARKGRAY)-($PCT\u$DARKGRAY)-($PCT\!
26 $DARKGRAY)$YELLOW-> $NC"
27
28 # Escape a variables whose value changes:
29 # if [[ \$EUID -eq 0 ]],
30 # Otherwise the value of the EUID variable will be assigned only once,
31 #+ as above.
32
33 # When a variable is assigned, it should be called escaped:
34 #+ echo \$T,
35 # Otherwise the value of the T variable is taken from the moment the PCT
36 #+ variable is exported/read from .bash_profile.
37 # So, in this example it would be null.
38
39 # When a variable's value contains a semicolon it should be strong quoted:
40 # T='$LIGHTRED',
41 # Otherwise, the semicolon will be interpreted as a command separator.
42
43
44 # Variables PCT and PS1 can be merged into a new PS1 variable:
45
46 PS1="\`if [[ \$EUID -eq 0 ]]; then PCT='$LIGHTRED';
47 else PCT='$LIGHTBLUE'; fi;
48 echo '\n$GREEN[\w] \n$DARKGRAY('\$PCT'\t$DARKGRAY)-\
49 ('\$PCT'\u$DARKGRAY)-('\$PCT'\!$DARKGRAY)$YELLOW-> $NC'\`"
50
51 # The trick is to use strong quoting for parts of old PS1 variable. |