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 M-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: Tue Nov 20 22:04:47 CET 2012
7
8 # This file is normally read by interactive shells only.
9 #+ Here is the place to define your aliases, functions and
10 #+ other interactive features like your prompt.
11 #
12 # The majority of the code here assumes you are on a GNU
13 #+ system (most likely a Linux box) and is often based on code
14 #+ found on Usenet or Internet.
15 #
16 # See for instance:
17 # http://tldp.org/LDP/abs/html/index.html
18 # http://www.caliban.org/bash
19 # http://www.shelldorado.com/scripts/categories.html
20 # http://www.dotfiles.org
21 #
22 # The choice of colors was done for a shell with a dark background
23 #+ (white on black), and this is usually also suited for pure text-mode
24 #+ consoles (no X server available). If you use a white background,
25 #+ you'll have to do some other choices for readability.
26 #
27 # This bashrc file is a bit overcrowded.
28 # Remember, it is just just an example.
29 # Tailor it to your needs.
30 #
31 # =============================================================== #
32
33 # --> Comments added by HOWTO author.
34
35 # If not running interactively, don't do anything
36 [ -z "$PS1" ] && return
37
38
39 #-------------------------------------------------------------
40 # Source global definitions (if any)
41 #-------------------------------------------------------------
42
43
44 if [ -f /etc/bashrc ]; then
45 . /etc/bashrc # --> Read /etc/bashrc, if present.
46 fi
47
48
49 #--------------------------------------------------------------
50 # Automatic setting of $DISPLAY (if not set already).
51 # This works for me - your mileage may vary. . . .
52 # The problem is that different types of terminals give
53 #+ different answers to 'who am i' (rxvt in particular can be
54 #+ troublesome) - however this code seems to work in a majority
55 #+ of cases.
56 #--------------------------------------------------------------
57
58 function get_xserver ()
59 {
60 case $TERM in
61 xterm )
62 XSERVER=$(who am i | awk '{print $NF}' | tr -d ')''(' )
63 # Ane-Pieter Wieringa suggests the following alternative:
64 # I_AM=$(who am i)
65 # SERVER=${I_AM#*(}
66 # SERVER=${SERVER%*)}
67 XSERVER=${XSERVER%%:*}
68 ;;
69 aterm | rxvt)
70 # Find some code that works here. ...
71 ;;
72 esac
73 }
74
75 if [ -z ${DISPLAY:=""} ]; then
76 get_xserver
77 if [[ -z ${XSERVER} || ${XSERVER} == $(hostname) ||
78 ${XSERVER} == "unix" ]]; then
79 DISPLAY=":0.0" # Display on local host.
80 else
81 DISPLAY=${XSERVER}:0.0 # Display on remote host.
82 fi
83 fi
84
85 export DISPLAY
86
87 #-------------------------------------------------------------
88 # Some settings
89 #-------------------------------------------------------------
90
91 #set -o nounset # These two options are useful for debugging.
92 #set -o xtrace
93 alias debug="set -o nounset; set -o xtrace"
94
95 ulimit -S -c 0 # Don't want coredumps.
96 set -o notify
97 set -o noclobber
98 set -o ignoreeof
99
100
101 # Enable options:
102 shopt -s cdspell
103 shopt -s cdable_vars
104 shopt -s checkhash
105 shopt -s checkwinsize
106 shopt -s sourcepath
107 shopt -s no_empty_cmd_completion
108 shopt -s cmdhist
109 shopt -s histappend histreedit histverify
110 shopt -s extglob # Necessary for programmable completion.
111
112 # Disable options:
113 shopt -u mailwarn
114 unset MAILCHECK # Don't want my shell to warn me of incoming mail.
115
116
117 #-------------------------------------------------------------
118 # Greeting, motd etc. ...
119 #-------------------------------------------------------------
120
121 # Color definitions (taken from Color Bash Prompt HowTo).
122 # Some colors might look different of some terminals.
123 # For example, I see 'Bold Red' as 'orange' on my screen,
124 # hence the 'Green' 'BRed' 'Red' sequence I often use in my prompt.
125
126
127 # Normal Colors
128 Black='\e[0;30m' # Black
129 Red='\e[0;31m' # Red
130 Green='\e[0;32m' # Green
131 Yellow='\e[0;33m' # Yellow
132 Blue='\e[0;34m' # Blue
133 Purple='\e[0;35m' # Purple
134 Cyan='\e[0;36m' # Cyan
135 White='\e[0;37m' # White
136
137 # Bold
138 BBlack='\e[1;30m' # Black
139 BRed='\e[1;31m' # Red
140 BGreen='\e[1;32m' # Green
141 BYellow='\e[1;33m' # Yellow
142 BBlue='\e[1;34m' # Blue
143 BPurple='\e[1;35m' # Purple
144 BCyan='\e[1;36m' # Cyan
145 BWhite='\e[1;37m' # White
146
147 # Background
148 On_Black='\e[40m' # Black
149 On_Red='\e[41m' # Red
150 On_Green='\e[42m' # Green
151 On_Yellow='\e[43m' # Yellow
152 On_Blue='\e[44m' # Blue
153 On_Purple='\e[45m' # Purple
154 On_Cyan='\e[46m' # Cyan
155 On_White='\e[47m' # White
156
157 NC="\e[m" # Color Reset
158
159
160 ALERT=${BWhite}${On_Red} # Bold White on red background
161
162
163
164 echo -e "${BCyan}This is BASH ${BRed}${BASH_VERSION%.*}${BCyan}\
165 - DISPLAY on ${BRed}$DISPLAY${NC}\n"
166 date
167 if [ -x /usr/games/fortune ]; then
168 /usr/games/fortune -s # Makes our day a bit more fun.... :-)
169 fi
170
171 function _exit() # Function to run upon exit of shell.
172 {
173 echo -e "${BRed}Hasta la vista, baby${NC}"
174 }
175 trap _exit EXIT
176
177 #-------------------------------------------------------------
178 # Shell Prompt - for many examples, see:
179 # http://www.debian-administration.org/articles/205
180 # http://www.askapache.com/linux/bash-power-prompt.html
181 # http://tldp.org/HOWTO/Bash-Prompt-HOWTO
182 # https://github.com/nojhan/liquidprompt
183 #-------------------------------------------------------------
184 # Current Format: [TIME USER@HOST PWD] >
185 # TIME:
186 # Green == machine load is low
187 # Orange == machine load is medium
188 # Red == machine load is high
189 # ALERT == machine load is very high
190 # USER:
191 # Cyan == normal user
192 # Orange == SU to user
193 # Red == root
194 # HOST:
195 # Cyan == local session
196 # Green == secured remote connection (via ssh)
197 # Red == unsecured remote connection
198 # PWD:
199 # Green == more than 10% free disk space
200 # Orange == less than 10% free disk space
201 # ALERT == less than 5% free disk space
202 # Red == current user does not have write privileges
203 # Cyan == current filesystem is size zero (like /proc)
204 # >:
205 # White == no background or suspended jobs in this shell
206 # Cyan == at least one background job in this shell
207 # Orange == at least one suspended job in this shell
208 #
209 # Command is added to the history file each time you hit enter,
210 # so it's available to all shells (using 'history -a').
211
212
213 # Test connection type:
214 if [ -n "${SSH_CONNECTION}" ]; then
215 CNX=${Green} # Connected on remote machine, via ssh (good).
216 elif [[ "${DISPLAY%%:0*}" != "" ]]; then
217 CNX=${ALERT} # Connected on remote machine, not via ssh (bad).
218 else
219 CNX=${BCyan} # Connected on local machine.
220 fi
221
222 # Test user type:
223 if [[ ${USER} == "root" ]]; then
224 SU=${Red} # User is root.
225 elif [[ ${USER} != $(logname) ]]; then
226 SU=${BRed} # User is not login user.
227 else
228 SU=${BCyan} # User is normal (well ... most of us are).
229 fi
230
231
232
233 NCPU=$(grep -c 'processor' /proc/cpuinfo) # Number of CPUs
234 SLOAD=$(( 100*${NCPU} )) # Small load
235 MLOAD=$(( 200*${NCPU} )) # Medium load
236 XLOAD=$(( 400*${NCPU} )) # Xlarge load
237
238 # Returns system load as percentage, i.e., '40' rather than '0.40)'.
239 function load()
240 {
241 local SYSLOAD=$(cut -d " " -f1 /proc/loadavg | tr -d '.')
242 # System load of the current host.
243 echo $((10#$SYSLOAD)) # Convert to decimal.
244 }
245
246 # Returns a color indicating system load.
247 function load_color()
248 {
249 local SYSLOAD=$(load)
250 if [ ${SYSLOAD} -gt ${XLOAD} ]; then
251 echo -en ${ALERT}
252 elif [ ${SYSLOAD} -gt ${MLOAD} ]; then
253 echo -en ${Red}
254 elif [ ${SYSLOAD} -gt ${SLOAD} ]; then
255 echo -en ${BRed}
256 else
257 echo -en ${Green}
258 fi
259 }
260
261 # Returns a color according to free disk space in $PWD.
262 function disk_color()
263 {
264 if [ ! -w "${PWD}" ] ; then
265 echo -en ${Red}
266 # No 'write' privilege in the current directory.
267 elif [ -s "${PWD}" ] ; then
268 local used=$(command df -P "$PWD" |
269 awk 'END {print $5} {sub(/%/,"")}')
270 if [ ${used} -gt 95 ]; then
271 echo -en ${ALERT} # Disk almost full (>95%).
272 elif [ ${used} -gt 90 ]; then
273 echo -en ${BRed} # Free disk space almost gone.
274 else
275 echo -en ${Green} # Free disk space is ok.
276 fi
277 else
278 echo -en ${Cyan}
279 # Current directory is size '0' (like /proc, /sys etc).
280 fi
281 }
282
283 # Returns a color according to running/suspended jobs.
284 function job_color()
285 {
286 if [ $(jobs -s | wc -l) -gt "0" ]; then
287 echo -en ${BRed}
288 elif [ $(jobs -r | wc -l) -gt "0" ] ; then
289 echo -en ${BCyan}
290 fi
291 }
292
293 # Adds some text in the terminal frame (if applicable).
294
295
296 # Now we construct the prompt.
297 PROMPT_COMMAND="history -a"
298 case ${TERM} in
299 *term | rxvt | linux)
300 PS1="\[\$(load_color)\][\A\[${NC}\] "
301 # Time of day (with load info):
302 PS1="\[\$(load_color)\][\A\[${NC}\] "
303 # User@Host (with connection type info):
304 PS1=${PS1}"\[${SU}\]\u\[${NC}\]@\[${CNX}\]\h\[${NC}\] "
305 # PWD (with 'disk space' info):
306 PS1=${PS1}"\[\$(disk_color)\]\W]\[${NC}\] "
307 # Prompt (with 'job' info):
308 PS1=${PS1}"\[\$(job_color)\]>\[${NC}\] "
309 # Set title of current xterm:
310 PS1=${PS1}"\[\e]0;[\u@\h] \w\a\]"
311 ;;
312 *)
313 PS1="(\A \u@\h \W) > " # --> PS1="(\A \u@\h \w) > "
314 # --> Shows full pathname of current dir.
315 ;;
316 esac
317
318
319
320 export TIMEFORMAT=$'\nreal %3R\tuser %3U\tsys %3S\tpcpu %P\n'
321 export HISTIGNORE="&:bg:fg:ll:h"
322 export HISTTIMEFORMAT="$(echo -e ${BCyan})[%d/%m %H:%M:%S]$(echo -e ${NC}) "
323 export HISTCONTROL=ignoredups
324 export HOSTFILE=$HOME/.hosts # Put a list of remote hosts in ~/.hosts
325
326
327 #============================================================
328 #
329 # ALIASES AND FUNCTIONS
330 #
331 # Arguably, some functions defined here are quite big.
332 # If you want to make this file smaller, these functions can
333 #+ be converted into scripts and removed from here.
334 #
335 #============================================================
336
337 #-------------------
338 # Personnal Aliases
339 #-------------------
340
341 alias rm='rm -i'
342 alias cp='cp -i'
343 alias mv='mv -i'
344 # -> Prevents accidentally clobbering files.
345 alias mkdir='mkdir -p'
346
347 alias h='history'
348 alias j='jobs -l'
349 alias which='type -a'
350 alias ..='cd ..'
351
352 # Pretty-print of some PATH variables:
353 alias path='echo -e ${PATH//:/\\n}'
354 alias libpath='echo -e ${LD_LIBRARY_PATH//:/\\n}'
355
356
357 alias du='du -kh' # Makes a more readable output.
358 alias df='df -kTh'
359
360 #-------------------------------------------------------------
361 # The 'ls' family (this assumes you use a recent GNU ls).
362 #-------------------------------------------------------------
363 # Add colors for filetype and human-readable sizes by default on 'ls':
364 alias ls='ls -h --color'
365 alias lx='ls -lXB' # Sort by extension.
366 alias lk='ls -lSr' # Sort by size, biggest last.
367 alias lt='ls -ltr' # Sort by date, most recent last.
368 alias lc='ls -ltcr' # Sort by/show change time,most recent last.
369 alias lu='ls -ltur' # Sort by/show access time,most recent last.
370
371 # The ubiquitous 'll': directories first, with alphanumeric sorting:
372 alias ll="ls -lv --group-directories-first"
373 alias lm='ll |more' # Pipe through 'more'
374 alias lr='ll -R' # Recursive ls.
375 alias la='ll -A' # Show hidden files.
376 alias tree='tree -Csuh' # Nice alternative to 'recursive ls' ...
377
378
379 #-------------------------------------------------------------
380 # Tailoring 'less'
381 #-------------------------------------------------------------
382
383 alias more='less'
384 export PAGER=less
385 export LESSCHARSET='latin1'
386 export LESSOPEN='|/usr/bin/lesspipe.sh %s 2>&-'
387 # Use this if lesspipe.sh exists.
388 export LESS='-i -N -w -z-4 -g -e -M -X -F -R -P%t?f%f \
389 :stdin .?pb%pb\%:?lbLine %lb:?bbByte %bb:-...'
390
391 # LESS man page colors (makes Man pages more readable).
392 export LESS_TERMCAP_mb=$'\E[01;31m'
393 export LESS_TERMCAP_md=$'\E[01;31m'
394 export LESS_TERMCAP_me=$'\E[0m'
395 export LESS_TERMCAP_se=$'\E[0m'
396 export LESS_TERMCAP_so=$'\E[01;44;33m'
397 export LESS_TERMCAP_ue=$'\E[0m'
398 export LESS_TERMCAP_us=$'\E[01;32m'
399
400
401 #-------------------------------------------------------------
402 # Spelling typos - highly personnal and keyboard-dependent :-)
403 #-------------------------------------------------------------
404
405 alias xs='cd'
406 alias vf='cd'
407 alias moer='more'
408 alias moew='more'
409 alias kk='ll'
410
411
412 #-------------------------------------------------------------
413 # A few fun ones
414 #-------------------------------------------------------------
415
416 # Adds some text in the terminal frame (if applicable).
417
418 function xtitle()
419 {
420 case "$TERM" in
421 *term* | rxvt)
422 echo -en "\e]0;$*\a" ;;
423 *) ;;
424 esac
425 }
426
427
428 # Aliases that use xtitle
429 alias top='xtitle Processes on $HOST && top'
430 alias make='xtitle Making $(basename $PWD) ; make'
431
432 # .. and functions
433 function man()
434 {
435 for i ; do
436 xtitle The $(basename $1|tr -d .[:digit:]) manual
437 command man -a "$i"
438 done
439 }
440
441
442 #-------------------------------------------------------------
443 # Make the following commands run in background automatically:
444 #-------------------------------------------------------------
445
446 function te() # wrapper around xemacs/gnuserv
447 {
448 if [ "$(gnuclient -batch -eval t 2>&-)" == "t" ]; then
449 gnuclient -q "$@";
450 else
451 ( xemacs "$@" &);
452 fi
453 }
454
455 function soffice() { command soffice "$@" & }
456 function firefox() { command firefox "$@" & }
457 function xpdf() { command xpdf "$@" & }
458
459
460 #-------------------------------------------------------------
461 # File & strings related functions:
462 #-------------------------------------------------------------
463
464
465 # Find a file with a pattern in name:
466 function ff() { find . -type f -iname '*'"$*"'*' -ls ; }
467
468 # Find a file with pattern $1 in name and Execute $2 on it:
469 function fe() { find . -type f -iname '*'"${1:-}"'*' \
470 -exec ${2:-file} {} \; ; }
471
472 # Find a pattern in a set of files and highlight them:
473 #+ (needs a recent version of egrep).
474 function fstr()
475 {
476 OPTIND=1
477 local mycase=""
478 local usage="fstr: find string in files.
479 Usage: fstr [-i] \"pattern\" [\"filename pattern\"] "
480 while getopts :it opt
481 do
482 case "$opt" in
483 i) mycase="-i " ;;
484 *) echo "$usage"; return ;;
485 esac
486 done
487 shift $(( $OPTIND - 1 ))
488 if [ "$#" -lt 1 ]; then
489 echo "$usage"
490 return;
491 fi
492 find . -type f -name "${2:-*}" -print0 | \
493 xargs -0 egrep --color=always -sn ${case} "$1" 2>&- | more
494
495 }
496
497
498 function swap()
499 { # Swap 2 filenames around, if they exist (from Uzi's bashrc).
500 local TMPFILE=tmp.$$
501
502 [ $# -ne 2 ] && echo "swap: 2 arguments needed" && return 1
503 [ ! -e $1 ] && echo "swap: $1 does not exist" && return 1
504 [ ! -e $2 ] && echo "swap: $2 does not exist" && return 1
505
506 mv "$1" $TMPFILE
507 mv "$2" "$1"
508 mv $TMPFILE "$2"
509 }
510
511 function extract() # Handy Extract Program
512 {
513 if [ -f $1 ] ; then
514 case $1 in
515 *.tar.bz2) tar xvjf $1 ;;
516 *.tar.gz) tar xvzf $1 ;;
517 *.bz2) bunzip2 $1 ;;
518 *.rar) unrar x $1 ;;
519 *.gz) gunzip $1 ;;
520 *.tar) tar xvf $1 ;;
521 *.tbz2) tar xvjf $1 ;;
522 *.tgz) tar xvzf $1 ;;
523 *.zip) unzip $1 ;;
524 *.Z) uncompress $1 ;;
525 *.7z) 7z x $1 ;;
526 *) echo "'$1' cannot be extracted via >extract<" ;;
527 esac
528 else
529 echo "'$1' is not a valid file!"
530 fi
531 }
532
533
534 # Creates an archive (*.tar.gz) from given directory.
535 function maketar() { tar cvzf "${1%%/}.tar.gz" "${1%%/}/"; }
536
537 # Create a ZIP archive of a file or folder.
538 function makezip() { zip -r "${1%%/}.zip" "$1" ; }
539
540 # Make your directories and files access rights sane.
541 function sanitize() { chmod -R u=rwX,g=rX,o= "$@" ;}
542
543 #-------------------------------------------------------------
544 # Process/system related functions:
545 #-------------------------------------------------------------
546
547
548 function my_ps() { ps $@ -u $USER -o pid,%cpu,%mem,bsdtime,command ; }
549 function pp() { my_ps f | awk '!/awk/ && $0~var' var=${1:-".*"} ; }
550
551
552 function killps() # kill by process name
553 {
554 local pid pname sig="-TERM" # default signal
555 if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then
556 echo "Usage: killps [-SIGNAL] pattern"
557 return;
558 fi
559 if [ $# = 2 ]; then sig=$1 ; fi
560 for pid in $(my_ps| awk '!/awk/ && $0~pat { print $1 }' pat=${!#} )
561 do
562 pname=$(my_ps | awk '$1~var { print $5 }' var=$pid )
563 if ask "Kill process $pid <$pname> with signal $sig?"
564 then kill $sig $pid
565 fi
566 done
567 }
568
569 function mydf() # Pretty-print of 'df' output.
570 { # Inspired by 'dfc' utility.
571 for fs ; do
572
573 if [ ! -d $fs ]
574 then
575 echo -e $fs" :No such file or directory" ; continue
576 fi
577
578 local info=( $(command df -P $fs | awk 'END{ print $2,$3,$5 }') )
579 local free=( $(command df -Pkh $fs | awk 'END{ print $4 }') )
580 local nbstars=$(( 20 * ${info[1]} / ${info[0]} ))
581 local out="["
582 for ((j=0;j<20;j++)); do
583 if [ ${j} -lt ${nbstars} ]; then
584 out=$out"*"
585 else
586 out=$out"-"
587 fi
588 done
589 out=${info[2]}" "$out"] ("$free" free on "$fs")"
590 echo -e $out
591 done
592 }
593
594
595 function my_ip() # Get IP adress on ethernet.
596 {
597 MY_IP=$(/sbin/ifconfig eth0 | awk '/inet/ { print $2 } ' |
598 sed -e s/addr://)
599 echo ${MY_IP:-"Not connected"}
600 }
601
602 function ii() # Get current host related info.
603 {
604 echo -e "\nYou are logged on ${BRed}$HOST"
605 echo -e "\n${BRed}Additionnal information:$NC " ; uname -a
606 echo -e "\n${BRed}Users logged on:$NC " ; w -hs |
607 cut -d " " -f1 | sort | uniq
608 echo -e "\n${BRed}Current date :$NC " ; date
609 echo -e "\n${BRed}Machine stats :$NC " ; uptime
610 echo -e "\n${BRed}Memory stats :$NC " ; free
611 echo -e "\n${BRed}Diskspace :$NC " ; mydf / $HOME
612 echo -e "\n${BRed}Local IP Address :$NC" ; my_ip
613 echo -e "\n${BRed}Open connections :$NC "; netstat -pan --inet;
614 echo
615 }
616
617 #-------------------------------------------------------------
618 # Misc utilities:
619 #-------------------------------------------------------------
620
621 function repeat() # Repeat n times command.
622 {
623 local i max
624 max=$1; shift;
625 for ((i=1; i <= max ; i++)); do # --> C-like syntax
626 eval "$@";
627 done
628 }
629
630
631 function ask() # See 'killps' for example of use.
632 {
633 echo -n "$@" '[y/n] ' ; read ans
634 case "$ans" in
635 y*|Y*) return 0 ;;
636 *) return 1 ;;
637 esac
638 }
639
640 function corename() # Get name of app that created a corefile.
641 {
642 for file ; do
643 echo -n $file : ; gdb --core=$file --batch | head -1
644 done
645 }
646
647
648
649 #=========================================================================
650 #
651 # PROGRAMMABLE COMPLETION SECTION
652 # Most are taken from the bash 2.05 documentation and from Ian McDonald's
653 # 'Bash completion' package (http://www.caliban.org/bash/#completion)
654 # You will in fact need bash more recent then 3.0 for some features.
655 #
656 # Note that most linux distributions now provide many completions
657 # 'out of the box' - however, you might need to make your own one day,
658 # so I kept those here as examples.
659 #=========================================================================
660
661 if [ "${BASH_VERSION%.*}" \< "3.0" ]; then
662 echo "You will need to upgrade to version 3.0 for full \
663 programmable completion features"
664 return
665 fi
666
667 shopt -s extglob # Necessary.
668
669 complete -A hostname rsh rcp telnet rlogin ftp ping disk
670 complete -A export printenv
671 complete -A variable export local readonly unset
672 complete -A enabled builtin
673 complete -A alias alias unalias
674 complete -A function function
675 complete -A user su mail finger
676
677 complete -A helptopic help # Currently same as builtins.
678 complete -A shopt shopt
679 complete -A stopped -P '%' bg
680 complete -A job -P '%' fg jobs disown
681
682 complete -A directory mkdir rmdir
683 complete -A directory -o default cd
684
685 # Compression
686 complete -f -o default -X '*.+(zip|ZIP)' zip
687 complete -f -o default -X '!*.+(zip|ZIP)' unzip
688 complete -f -o default -X '*.+(z|Z)' compress
689 complete -f -o default -X '!*.+(z|Z)' uncompress
690 complete -f -o default -X '*.+(gz|GZ)' gzip
691 complete -f -o default -X '!*.+(gz|GZ)' gunzip
692 complete -f -o default -X '*.+(bz2|BZ2)' bzip2
693 complete -f -o default -X '!*.+(bz2|BZ2)' bunzip2
694 complete -f -o default -X '!*.+(zip|ZIP|z|Z|gz|GZ|bz2|BZ2)' extract
695
696
697 # Documents - Postscript,pdf,dvi.....
698 complete -f -o default -X '!*.+(ps|PS)' gs ghostview ps2pdf ps2ascii
699 complete -f -o default -X \
700 '!*.+(dvi|DVI)' dvips dvipdf xdvi dviselect dvitype
701 complete -f -o default -X '!*.+(pdf|PDF)' acroread pdf2ps
702 complete -f -o default -X '!*.@(@(?(e)ps|?(E)PS|pdf|PDF)?\
703 (.gz|.GZ|.bz2|.BZ2|.Z))' gv ggv
704 complete -f -o default -X '!*.texi*' makeinfo texi2dvi texi2html texi2pdf
705 complete -f -o default -X '!*.tex' tex latex slitex
706 complete -f -o default -X '!*.lyx' lyx
707 complete -f -o default -X '!*.+(htm*|HTM*)' lynx html2ps
708 complete -f -o default -X \
709 '!*.+(doc|DOC|xls|XLS|ppt|PPT|sx?|SX?|csv|CSV|od?|OD?|ott|OTT)' soffice
710
711 # Multimedia
712 complete -f -o default -X \
713 '!*.+(gif|GIF|jp*g|JP*G|bmp|BMP|xpm|XPM|png|PNG)' xv gimp ee gqview
714 complete -f -o default -X '!*.+(mp3|MP3)' mpg123 mpg321
715 complete -f -o default -X '!*.+(ogg|OGG)' ogg123
716 complete -f -o default -X \
717 '!*.@(mp[23]|MP[23]|ogg|OGG|wav|WAV|pls|\
718 m3u|xm|mod|s[3t]m|it|mtm|ult|flac)' xmms
719 complete -f -o default -X '!*.@(mp?(e)g|MP?(E)G|wma|avi|AVI|\
720 asf|vob|VOB|bin|dat|vcd|ps|pes|fli|viv|rm|ram|yuv|mov|MOV|qt|\
721 QT|wmv|mp3|MP3|ogg|OGG|ogm|OGM|mp4|MP4|wav|WAV|asx|ASX)' xine
722
723
724
725 complete -f -o default -X '!*.pl' perl perl5
726
727
728 # This is a 'universal' completion function - it works when commands have
729 #+ a so-called 'long options' mode , ie: 'ls --all' instead of 'ls -a'
730 # Needs the '-o' option of grep
731 #+ (try the commented-out version if not available).
732
733 # First, remove '=' from completion word separators
734 #+ (this will allow completions like 'ls --color=auto' to work correctly).
735
736 COMP_WORDBREAKS=${COMP_WORDBREAKS/=/}
737
738
739 _get_longopts()
740 {
741 #$1 --help | sed -e '/--/!d' -e 's/.*--\([^[:space:].,]*\).*/--\1/'| \
742 #grep ^"$2" |sort -u ;
743 $1 --help | grep -o -e "--[^[:space:].,]*" | grep -e "$2" |sort -u
744 }
745
746 _longopts()
747 {
748 local cur
749 cur=${COMP_WORDS[COMP_CWORD]}
750
751 case "${cur:-*}" in
752 -*) ;;
753 *) return ;;
754 esac
755
756 case "$1" in
757 \~*) eval cmd="$1" ;;
758 *) cmd="$1" ;;
759 esac
760 COMPREPLY=( $(_get_longopts ${1} ${cur} ) )
761 }
762 complete -o default -F _longopts configure bash
763 complete -o default -F _longopts wget id info a2ps ls recode
764
765 _tar()
766 {
767 local cur ext regex tar untar
768
769 COMPREPLY=()
770 cur=${COMP_WORDS[COMP_CWORD]}
771
772 # If we want an option, return the possible long options.
773 case "$cur" in
774 -*) COMPREPLY=( $(_get_longopts $1 $cur ) ); return 0;;
775 esac
776
777 if [ $COMP_CWORD -eq 1 ]; then
778 COMPREPLY=( $( compgen -W 'c t x u r d A' -- $cur ) )
779 return 0
780 fi
781
782 case "${COMP_WORDS[1]}" in
783 ?(-)c*f)
784 COMPREPLY=( $( compgen -f $cur ) )
785 return 0
786 ;;
787 +([^Izjy])f)
788 ext='tar'
789 regex=$ext
790 ;;
791 *z*f)
792 ext='tar.gz'
793 regex='t\(ar\.\)\(gz\|Z\)'
794 ;;
795 *[Ijy]*f)
796 ext='t?(ar.)bz?(2)'
797 regex='t\(ar\.\)bz2\?'
798 ;;
799 *)
800 COMPREPLY=( $( compgen -f $cur ) )
801 return 0
802 ;;
803
804 esac
805
806 if [[ "$COMP_LINE" == tar*.$ext' '* ]]; then
807 # Complete on files in tar file.
808 #
809 # Get name of tar file from command line.
810 tar=$( echo "$COMP_LINE" | \
811 sed -e 's|^.* \([^ ]*'$regex'\) .*$|\1|' )
812 # Devise how to untar and list it.
813 untar=t${COMP_WORDS[1]//[^Izjyf]/}
814
815 COMPREPLY=( $( compgen -W "$( echo $( tar $untar $tar \
816 2>/dev/null ) )" -- "$cur" ) )
817 return 0
818
819 else
820 # File completion on relevant files.
821 COMPREPLY=( $( compgen -G $cur\*.$ext ) )
822
823 fi
824
825 return 0
826
827 }
828
829 complete -F _tar -o default tar
830
831 _make()
832 {
833 local mdef makef makef_dir="." makef_inc gcmd cur prev i;
834 COMPREPLY=();
835 cur=${COMP_WORDS[COMP_CWORD]};
836 prev=${COMP_WORDS[COMP_CWORD-1]};
837 case "$prev" in
838 -*f)
839 COMPREPLY=($(compgen -f $cur ));
840 return 0
841 ;;
842 esac;
843 case "$cur" in
844 -*)
845 COMPREPLY=($(_get_longopts $1 $cur ));
846 return 0
847 ;;
848 esac;
849
850 # ... make reads
851 # GNUmakefile,
852 # then makefile
853 # then Makefile ...
854 if [ -f ${makef_dir}/GNUmakefile ]; then
855 makef=${makef_dir}/GNUmakefile
856 elif [ -f ${makef_dir}/makefile ]; then
857 makef=${makef_dir}/makefile
858 elif [ -f ${makef_dir}/Makefile ]; then
859 makef=${makef_dir}/Makefile
860 else
861 makef=${makef_dir}/*.mk # Local convention.
862 fi
863
864
865 # Before we scan for targets, see if a Makefile name was
866 #+ specified with -f.
867 for (( i=0; i < ${#COMP_WORDS[@]}; i++ )); do
868 if [[ ${COMP_WORDS[i]} == -f ]]; then
869 # eval for tilde expansion
870 eval makef=${COMP_WORDS[i+1]}
871 break
872 fi
873 done
874 [ ! -f $makef ] && return 0
875
876 # Deal with included Makefiles.
877 makef_inc=$( grep -E '^-?include' $makef |
878 sed -e "s,^.* ,"$makef_dir"/," )
879 for file in $makef_inc; do
880 [ -f $file ] && makef="$makef $file"
881 done
882
883
884 # If we have a partial word to complete, restrict completions
885 #+ to matches of that word.
886 if [ -n "$cur" ]; then gcmd='grep "^$cur"' ; else gcmd=cat ; fi
887
888 COMPREPLY=( $( awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ \
889 {split($1,A,/ /);for(i in A)print A[i]}' \
890 $makef 2>/dev/null | eval $gcmd ))
891
892 }
893
894 complete -F _make -X '+($*|*.[cho])' make gmake pmake
895
896
897
898
899 _killall()
900 {
901 local cur prev
902 COMPREPLY=()
903 cur=${COMP_WORDS[COMP_CWORD]}
904
905 # Get a list of processes
906 #+ (the first sed evaluation
907 #+ takes care of swapped out processes, the second
908 #+ takes care of getting the basename of the process).
909 COMPREPLY=( $( ps -u $USER -o comm | \
910 sed -e '1,1d' -e 's#[]\[]##g' -e 's#^.*/##'| \
911 awk '{if ($0 ~ /^'$cur'/) print $0}' ))
912
913 return 0
914 }
915
916 complete -F _killall killall killps
917
918
919
920 # Local Variables:
921 # mode:shell-script
922 # sh-shell:bash
923 # End: |
And, here is a snippet from Andrzej Szelachowski's instructive .bash_profile file.
Example M-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. |