- •Table of Contents
- •Chapter 1. Why Shell Programming?
- •2.1. Invoking the script
- •2.2. Preliminary Exercises
- •Part 2. Basics
- •Chapter 3. Exit and Exit Status
- •Chapter 4. Special Characters
- •Chapter 5. Introduction to Variables and Parameters
- •5.1. Variable Substitution
- •5.2. Variable Assignment
- •5.3. Bash Variables Are Untyped
- •5.4. Special Variable Types
- •Chapter 6. Quoting
- •Chapter 7. Tests
- •7.1. Test Constructs
- •7.2. File test operators
- •7.3. Comparison operators (binary)
- •7.4. Nested if/then Condition Tests
- •7.5. Testing Your Knowledge of Tests
- •Chapter 8. Operations and Related Topics
- •8.1. Operators
- •8.2. Numerical Constants
- •Part 3. Beyond the Basics
- •Chapter 9. Variables Revisited
- •9.1. Internal Variables
- •9.2. Manipulating Strings
- •9.2.1. Manipulating strings using awk
- •9.2.2. Further Discussion
- •9.3. Parameter Substitution
- •9.4. Typing variables: declare or typeset
- •9.5. Indirect References to Variables
- •9.6. $RANDOM: generate random integer
- •9.7. The Double Parentheses Construct
- •Chapter 10. Loops and Branches
- •10.1. Loops
- •10.2. Nested Loops
- •10.3. Loop Control
- •10.4. Testing and Branching
- •Chapter 11. Internal Commands and Builtins
- •11.1. Job Control Commands
- •Chapter 12. External Filters, Programs and Commands
- •12.1. Basic Commands
- •12.2. Complex Commands
- •12.3. Time / Date Commands
- •12.4. Text Processing Commands
- •12.5. File and Archiving Commands
- •12.6. Communications Commands
- •12.7. Terminal Control Commands
- •12.8. Math Commands
- •12.9. Miscellaneous Commands
- •Chapter 13. System and Administrative Commands
- •Chapter 14. Command Substitution
- •Chapter 15. Arithmetic Expansion
- •Chapter 16. I/O Redirection
- •16.1. Using exec
- •16.2. Redirecting Code Blocks
- •16.3. Applications
- •Chapter 17. Here Documents
- •Chapter 18. Recess Time
- •Part 4. Advanced Topics
- •Chapter 19. Regular Expressions
- •19.1. A Brief Introduction to Regular Expressions
- •19.2. Globbing
- •Chapter 20. Subshells
- •Chapter 21. Restricted Shells
- •Chapter 22. Process Substitution
- •Chapter 23. Functions
- •23.1. Complex Functions and Function Complexities
- •23.2. Local Variables
- •23.2.1. Local variables make recursion possible.
- •Chapter 24. Aliases
- •Chapter 25. List Constructs
- •Chapter 26. Arrays
- •Chapter 27. Files
- •Chapter 28. /dev and /proc
- •28.2. /proc
- •Chapter 29. Of Zeros and Nulls
- •Chapter 30. Debugging
- •Chapter 31. Options
- •Chapter 32. Gotchas
- •Chapter 33. Scripting With Style
- •33.1. Unofficial Shell Scripting Stylesheet
- •Chapter 34. Miscellany
- •34.2. Shell Wrappers
- •34.3. Tests and Comparisons: Alternatives
- •34.4. Optimizations
- •34.5. Assorted Tips
- •34.6. Oddities
- •34.7. Portability Issues
- •34.8. Shell Scripting Under Windows
- •Chapter 35. Bash, version 2
- •Chapter 36. Endnotes
- •36.1. Author's Note
- •36.2. About the Author
- •36.3. Tools Used to Produce This Book
- •36.3.1. Hardware
- •36.3.2. Software and Printware
- •36.4. Credits
- •Bibliography
- •Appendix A. Contributed Scripts
- •Appendix C. Exit Codes With Special Meanings
- •Appendix D. A Detailed Introduction to I/O and I/O Redirection
- •Appendix E. Localization
- •Appendix F. History Commands
- •Appendix G. A Sample .bashrc File
- •Appendix H. Converting DOS Batch Files to Shell Scripts
- •Appendix I. Exercises
- •Appendix J. Copyright
Chapter 24. Aliases
A Bash alias is essentially nothing more than a keyboard shortcut, an abbreviation, a means of avoiding typing a long command sequence. If, for example, we include alias lm="ls −l | more" in the
~/.bashrc file, then each lm typed at the command line will automatically be replaced by a ls −l | more. This can save a great deal of typing at the command line and avoid having to remember complex combinations of commands and options. Setting alias rm="rm −i" (interactive mode delete) may save a good deal of grief, since it can prevent inadvertently losing important files.
In a script, aliases have very limited usefulness. It would be quite nice if aliases could assume some of the functionality of the C preprocessor, such as macro expansion, but unfortunately Bash does not expand arguments within the alias body. [54] Moreover, a script fails to expand an alias itself within "compound constructs", such as if/then statements, loops, and functions. An added limitation is that an alias will not expand recursively. Almost invariably, whatever we would like an alias to do could be accomplished much more effectively with a function.
Example 24−1. Aliases within a script
#!/bin/bash
# May need to be invoked with #!/bin/bash2 on older systems.
shopt −s expand_aliases
#Must set this option, else script will not expand aliases.
#First, some fun.
alias Jesse_James='echo "\"Alias Jesse James\" was a 1959 comedy starring Bob Hope."' Jesse_James
echo; echo; echo;
alias ll="ls −l"
# May use either single (') or double (") quotes to define an alias.
echo "Trying aliased \"ll\":"
ll /usr/X11R6/bin/mk* |
#* Alias works. |
echo |
|
directory=/usr/X11R6/bin/
prefix=mk* # See if wild−card causes problems.
echo "Variables \"directory\" + \"prefix\" = $directory$prefix" echo
alias lll="ls −l $directory$prefix"
echo "Trying aliased \"lll\":"
lll # Long listing of all files in /usr/X11R6/bin stating with mk.
# Alias handles concatenated variables, including wild−card o.k.
TRUE=1
Chapter 24. Aliases |
257 |
Advanced Bash−Scripting Guide
echo
if [ TRUE ] then
alias rr="ls −l"
echo "Trying aliased \"rr\" within if/then statement:" rr /usr/X11R6/bin/mk* #* Error message results!
# Aliases not expanded within compound statements.
echo "However, previously expanded alias still recognized:" ll /usr/X11R6/bin/mk*
fi
echo
count=0
while [ $count −lt 3 ] do
alias rrr="ls −l"
echo "Trying aliased \"rrr\" within \"while\" loop:"
rrr |
/usr/X11R6/bin/mk* #* Alias will not expand here either. |
let |
count+=1 |
done |
|
echo; |
echo |
alias |
xyz="cat $1" # Try a positional parameter in an alias. |
xyz |
# If you invoke the script with a filename as a parameter. |
#This seems to work,
#+ although the Bash documentation suggests that it shouldn't.
exit 0
The unalias command removes a previously set alias.
Example 24−2. unalias: Setting and unsetting an alias
#!/bin/bash
shopt −s expand_aliases # Enables alias expansion.
alias llm='ls −al | more' llm
echo |
|
|
|
|
|
|
|
unalias llm |
|
|
# Unset alias. |
|
|
|
|
llm |
|
|
|
|
|
|
|
# Error message results, since 'llm' no longer recognized. |
|||||||
exit 0 |
|
|
|
|
|
|
|
bash$ ./unalias.sh |
|
|
|
|
|
||
total 6 |
|
|
|
|
|
|
|
drwxrwxr−x |
2 |
bozo |
bozo |
3072 |
Feb |
6 |
14:04 . |
drwxr−xr−x |
40 |
bozo |
bozo |
2048 |
Feb |
6 |
14:04 .. |
−rwxr−xr−x |
1 |
bozo |
bozo |
199 |
Feb |
6 |
14:04 unalias.sh |
./unalias.sh: llm: command not found
Chapter 24. Aliases |
258 |
Advanced Bash−Scripting Guide
Chapter 24. Aliases |
259 |
Chapter 25. List Constructs
The "and list" and "or list" constructs provide a means of processing a number of commands consecutively. These can effectively replace complex nested if/then or even case statements.
Chaining together commands
and list
command−1 && command−2 && command−3 && ... command−n
Each command executes in turn provided that the previous command has given a return value of true (zero). At the first false (non−zero) return, the command chain terminates (the first command returning false is the last one to execute).
Example 25−1. Using an "and list" to test for command−line arguments
#!/bin/bash
# "and list"
if [ ! −z "$1" ] && echo "Argument #1 = $1" && [ ! −z "$2" ] && echo "Argument #2 = $2" then
echo "At least 2 arguments passed to script."
#All the chained commands return true.
else
echo "Less than 2 arguments passed to script."
#At least one of the chained commands returns false.
fi
#Note that "if [ ! −z $1 ]" works, but its supposed equivalent,
#if [ −n $1 ] does not. However, quoting fixes this.
#if [ −n "$1" ] works. Careful!
#It is best to always quote tested variables.
#This accomplishes the same thing, using "pure" if/then statements. if [ ! −z "$1" ]
then
echo "Argument #1 = $1"
fi
if [ ! −z "$2" ] then
echo "Argument #2 = $2"
echo "At least 2 arguments passed to script." else
echo "Less than 2 arguments passed to script."
fi
#It's longer and less elegant than using an "and list".
exit 0
Example 25−2. Another command−line arg test using an "and list"
#!/bin/bash
ARGS=1 |
# Number of arguments expected. |
Chapter 25. List Constructs |
260 |
Advanced Bash−Scripting Guide
E_BADARGS=65 # Exit value if incorrect number of args passed.
test $# −ne $ARGS && echo "Usage: `basename $0` $ARGS argument(s)" && exit $E_BADARGS
#If condition−1 true (wrong number of args passed to script),
#then the rest of the line executes, and script terminates.
#Line below executes only if the above test fails.
echo "Correct number of arguments passed to this script."
exit 0
# To check exit value, do a "echo $?" after script termination.
or list
command−1 || command−2 || command−3 || ... command−n
Each command executes in turn for as long as the previous command returns false. At the first true return, the command chain terminates (the first command returning true is the last one to execute). This is obviously the inverse of the "and list".
Example 25−3. Using "or lists" in combination with an "and list"
#!/bin/bash
#"Delete", not−so−cunning file deletion utility.
#Usage: delete filename
E_BADARGS=65
if [ −z "$1" ] then
echo "Usage: `basename $0` filename" exit $E_BADARGS
fi
file=$1 # Set filename.
[ ! −f "$1" ] && echo "File \"$1\" not found. \ Cowardly refusing to delete a nonexistent file."
#AND LIST, to give error message if file not present.
#Note echo message continued on to a second line with an escape.
[ ! −f "$1" ] || (rm −f $1; echo "File \"$file\" deleted.")
#OR LIST, to delete file if present.
#( command1 ; command2 ) is, in effect, an AND LIST variant.
#Note logic inversion above.
#AND LIST executes on true, OR LIST on false.
exit 0
If the first command in an "or list" returns true, it will execute.
The exit status of an and list or an or list is the exit status of the last command executed.
Chapter 25. List Constructs |
261 |
Advanced Bash−Scripting Guide
Clever combinations of "and" and "or" lists are possible, but the logic may easily become convoluted and require extensive debugging.
false |
&& true || echo false |
# false |
||
# Same result as |
|
|
||
( |
false && true ) || echo false |
# |
false |
|
# |
But |
*not* |
|
|
false |
&& ( true || echo false ) |
# |
(nothing echoed) |
#Note left−to−right grouping and evaluation of statements,
#since the logic operators "&&" and "||" have equal precedence.
#It's best to avoid such complexities, unless you know what you're doing.
#Thanks, S.C.
See Example A−6 for an illustration of using an and / or list to test variables.
Chapter 25. List Constructs |
262 |