How to extend bash aliases
Bash stores the values of aliases in an array called
BASH_ALIASES
:
$ alias foo=bar
$ echo ${BASH_ALIASES[foo]}
bar
With parameter expansion we can get the either the last set alias (if exists) or the default value:
alias grep="${BASH_ALIASES[grep]:-grep} -I --exclude=\*~"
Now just do it on setup-java.sh
:
alias grep="${BASH_ALIASES[grep]:-grep} -I --exclude=\*~ --exclude-dir=classes"
...and finally on setup-sass.sh
:
alias grep="${BASH_ALIASES[grep]:-grep} -I --exclude=\*~ --exclude-dir=\*/.sass-cache"
If the three lines are called, we get what we want:
$ echo ${BASH_ALIASES[grep]:-grep}
grep -I --exclude=\*~ -I --exclude=\*~ --exclude-dir=classes -I --exclude=\*~ --exclude-dir=\*/.sass-cache
aliases
chain if you end them with spaces.
alias print='printf %s\\n ' hey='"hello, fine fellow" '
print hey
hello, fine fellow
You can write entire scripts that way, if you're crazy enough. Anyway, if you want to extend an alias, then just make sure the alias you want to extend ends in a space, and tack another on.
alias grep='printf "%s " -I --exclude=\*~ ' \
exdir=' --exclude-dir=classes ' \
exsass='--exclude-dir=\*/.sass-cache '
grep exdir exsass exdir exsass
-I --exclude=*~ --exclude-dir=classes --exclude-dir=*/.sass-cache --exclude-dir=classes --exclude-dir=*/.sass-cache
A function is a better option than an extendable alias here.
grep_options=( )
grep() {
exec /usr/bin/grep "${grep_options[@]}" ${GREP_OPTIONS} "$@"
}
That way, you have two options to add options to the environment:
Amend the
grep_options
array; this correctly supports options with spaces, literal glob characters, and other corner cases:grep_options+=( --exclude-dir=classes --exclude-dir='*/.sass-cache' )
Use the traditional
GREP_OPTIONS
scalar variable, despite its pitfalls (see BashFAQ #50 to understand some of these):GREP_OPTIONS+=' --exclude-dir=classes '
That said, if you want your options to be reflected by grep
instances invoked outside the shell, neither an alias nor a function will do. Instead, you'll want a wrapper script placed earlier in your PATH than the real grep
command. For instance:
# in ~/.bash_profile
[[ -e ~/bin ]] && PATH=$HOME/bin:$PATH
...and, in ~/bin/grep
:
#!/bin/bash
# load overrides to grep_options on GREP_OPTIONS from local dotfiles
source ~/.bash_profile
source ~/.bashrc
# ...and use them:
exec /usr/bin/grep "${grep_options[@]}" ${GREP_OPTIONS} "$@"