Previous | Table of Contents | Next |
Now that the mytar script uses options to set the mode in which the script runs, you have another problem to solve. Namely, what should it do if the second argument, $2, is not provided?
You dont have to worry about what happens if the first argument, $1, is not provided because the case statement deals with this situation via the default case, *.
The simplest method for checking the necessary number of arguments is to see whether the number of given arguments, $#, matches the number of required arguments. Add this check to the script:
#!/bin/sh USAGE="Usage: 'basename $0' [-c|-t] [file|directory]" if [ $# -lt 2 ] ; then echo "$USAGE" exit 1 fi case "$1" in -t) TARGS="-tvf $2" ;; -c) TARGS="-cvf $2.tar $2" ;; *) echo "$USAGE" exit 0 ;; esac tar $TARGS
Handling Additional Files
This mytar script is mostly finished, but you can still make a few improvements. For example, it only deals with the first file that is given as an argument, and it does not check to see whether the file argument is really a file.
You can add the processing of all file arguments by using the special shell variable $@. Start with the t (list contents) option. The case statement now becomes
case "$1" in -t) TARGS="-tvf" for i in "$@" ; do if [ -f "$i" ] ; then tar $TARGS "$i" ; fi ; done ;; -c) TARGS="-cvf $2.tar $2" ; tar $TARGS ;; *) echo "$USAGE" ; exit 0 ;; esac
The main change is that the t case now includes a for loop that cycles through the arguments and checks to see whether each one is a file. If an argument is a file, tar is invoked on that file.
Caution:
When examining the arguments passed to a script, two special variables are available for inspection, $* and $@.The main difference between these two is how they expand arguments. When $* is used, it simply expands each argument without preserving quoting. This can sometimes cause a problem. If your script is given a filename containing spaces as an argument,
mytar t "my tar file.tar"using $* would mean that the for loop would call tar three times for files named my, tar, and file.tar, instead of once for the file you requested: my tar file.tar.
By using $@, you avoid this problem because it expands each argument as it was quoted on the command line.
Some Minor Issues
You should deal with a few more minor issues. Looking closely, you see that all the arguments given to the script, including the first argument, $1, are considered as files. Because you are using the first argument as the flag to indicate the mode in which the script runs, you should not consider it.
Not only does this reduce the number of times the for loop runs, but it also prevents the script from accidentally trying to run tar on a file with the name -t. To remove the first argument from the list of arguments, use the shift command. A similar change to the make mode of the script is also required.
Another issue is what the script should do when an operation fails. In the case of the listing operation, if the tar cannot list the contents of a file, skipping the file and printing an error would be a reasonable operation. Because the shell sets the variable $? to the exit status of the most recent command, you can use that to determine whether a tar operation failed.
Resolving the previous issues, your script is as follows:
#!/bin/sh USAGE="Usage: 'basename $0' [-c|-t] [files|directories]" if [ $# -lt 2 ] ; then echo "$USAGE" ; exit 1 ; fi case "$1" in -t) shift ; TARGS="-tvf" ; for i in "$@" ; do if [ -f "$i" ] ; then FILES='tar $TARGS "$i" 2>/dev/null' if [ $? -eq 0 ] ; then echo ; echo "$i" ; echo "$FILES" else echo "ERROR: $i not a tar file." fi else echo "ERROR: $i not a file." fi done ;; -c) shift ; TARGS="-cvf" ; tar $TARGS archive.tar "$@" ;; *) echo "$USAGE" exit 0 ;; esac exit $?
You have two common ways to handle the parsing of options passed to a shell script. In the first method, you can manually deal with the options using a case statement. This method was used in the mytar script presented earlier in the chapter. The second method, discussed in this section, is to use the getopts command.
The syntax of the getopts command is
getopts option-string variable
Here option-string is a string consisting of all the single character options getopts should consider, and variable is the name of the variable that the option should be set to. Usually the variable used is named OPTION.
The process by which getopts parses the options given on the command line is
Another feature of getopts is the capability to indicate options requiring an additional parameter. You can accomplish this by following the option with a : character in the option-string. In this case, after an option is parsed, the additional parameter is set to the value of the variable named OPTARG.
Previous | Table of Contents | Next |