 |
|
Using Quotes in Shell Scripts
Linux Tips by Burleson Consulting |
Since the use of the
backward quote (Formally, a ?grave?, pronounced Gra-vee) or backtick has been
mentioned, this is probably a good time to explain the rules regarding the use
of quotes:
* Double quote (?): Variables are expanded when enclosed
in double quotes
* Single quote (?): Variables within single quotes are
not expanded
* Backward quote (`): Commands within backward quotes
are executed and their output substituted into that location.
The following examples should help make the differences
between the types of quotes more evident.
$ myname='Terry Clark'
$ echo 'My name is $myname'
My name is $myname
$ echo "My name is $myname"
My name is Terry Clark
$ echo 'The name of this computer is `hostname`'
The name of this computer is `hostname`
$ echo "The name of this computer is `hostname`"
The name of this computer is appsvr.mytec.com
So we see that when enclosed in single quotes text is
treated very literally, but when enclosed in double quotes variables and
commands in backward quotes are evaluated and their values output.
Exit Status
Whenever a command or shell script completes
successfully, it sets a hidden status code of zero. If the command is
unsuccessful, it sets a nonzero hidden status code. This completion status code
is known as the exit status. The exit status of the last command or script that
was run is contained in the special shell variable, $?.
Most of the time we never look at this value and instead
check to see if the command did what we want or look for errors in the output of
commands. In a shell script, however, we may want to check the exit status to
make sure everything is going OK. The exit status of the last command can be
displayed as follows:
$ ls
example1.fil example2.xxx examples test.bsh
umask_example.fil
$ echo $?
0
$ ls *.txt
ls: *.txt: No such file or directory
$ echo $?
1
The conditional statements shown later in this section
can be used to make decisions based on the exit status of the previous command.
This can be useful for handling and reporting errors in a shell script.
The read Statement
The read command is used to accept input from standard
input such as a keyboard and store it into variables. This is useful if you
want to prompt for input from the user running your script.
The read command reads one line from the standard input
and the first word is assigned to the first variable, the second word to the
second variable, and so on, with leftover words assigned to the last variable.
If there are fewer words read from the input stream than variables, the
remaining variables are assigned empty values.
Here are some examples of the read command:
$ read name1 name2
Terry Clark
$ echo $name2
Clark
$ echo "Name1: $name1 Name2: $name2"
Name1: Terry Name2: Clark
$ read fullname
Terry L. Clark
$ echo $fullname
Terry L. Clark
The ?p option can be used to specify a prompt to be
displayed to the user. The prompt can be used to request that the user enter
specific information. The following is an example of using read with the ?p
option to prompt the user for input:
$ read -p "Enter your name please: " fullname
Enter your name please:
Terry Clark
$ echo $fullname
Terry Clark
Now you can start to see how we can make an interactive
shell script which prompts the user for input. Sometimes we want to collect
information when the shell script is started rather than once it is running.
For that type of information command line arguments can be used.
Command Line Arguments
Arguments or parameters can be passed to the script from
the command line that invoked the script just like we have been passing
arguments to commands. Arguments passed to the script are available in special
shell variables which are referenced by number. The first argument can be
referenced using the variable $1, the second argument using $2, etc. The $0
variable is special and contains the name of the command used to invoke the
script or command name. The following is an example of using command line
arguments.
#
# This script accepts a user?s first and last name and
# displays the current login username, hostname, and
home
# directory.
#
firstname=$1
lastname=$2
echo " "
echo " Hello $1"
echo " You are logged in as: $USER on server:
$HOSTNAME"
echo " Your home directory is: $HOME "
echo " Thank you, $firstname $lastname for invoking the
$0 command"
echo " "
Note that anything after a pound sign (#) in a shell
script is a comment and will be ignored when the script is run.
If we were to run the above script here is what you
would get as a result:
$ ./mylogin Terry Clark
Hello Terry
You are logged in as: tclark on server:
appsvr.mytec.com
Your home directory is: /home/tclark
Thank you, Terry Clark for invoking the ./mylogin
command
We can see how the script has captured the input and
substituted the $0, $1 and $2 variables into the context of the output. We have
also used some of the global shell variables discussed earlier like $USER,
$HOSTNAME and $HOME.
Sometimes the input you're looking for won't come from a
user at a keyboard but rather from a file or from the output of another
command. Other times you may want to output information to an output file or a
log. Next we'll look at how to do these things within your shell commands and
scripts.
Redirection of Standard Input & Output
In Linux, the standard input device is the keyboard, and
the standard output device is the display screen. These are the defaults for
input and output; however, Linux does allow the redirection of both standard
input and output to files. In other words, Linux accepts input from files and
can direct output to files.
Three symbols are used to indicate redirection to
Linux. Table 8.2 below shows the meanings of the symbols:
Symbol |
Meaning |
< |
Accept input from a file instead of
the keyboard |
> |
Send output to a file instead of the
display device (overwriting the file) |
>> |
Append output to the end of the
indicated file. For example, keep a log file. |
Table 8.2: Redirection symbols and their meanings
The following is an example of redirecting command
output to a file using the > symbol. We then examine the file with the cat
command.
$ ls -alt > dir.lst
$ cat dir.lst
total 68
drwx------ 4 tclark tclark 4096 Feb 24 23:27
.
-rw-rw-r-- 1 tclark tclark 0 Feb 24 23:27
dir.lst
-rw------- 1 tclark tclark 11629 Feb 24 21:24
.bash_history
-rwxrwxr-x 1 tclark tclark 325 Feb 24 21:17
mylogin
-rw------- 1 tclark tclark 4151 Feb 24 21:17
.viminfo
-rwxrwxr-x 1 tclark tclark 208 Feb 19 22:52
test.bsh
drwxrwxr-x 2 tclark authors 4096 Feb 3 23:11
examples
-rw-rw-r-- 1 tclark tclark 0 Feb 3 09:00
example1.fil
-rw-r--r-- 1 tclark authors 0 Jan 27 00:22
umask_example.fil
drwxr-xr-x 8 root root 4096 Jan 25 22:16
..
-rw-rw-r-- 1 tclark tclark 0 Jan 13 21:13
example2.xxx
-rw-r--r-- 1 tclark tclark 120 Aug 24 2004
.gtkrc
-rw-r--r-- 1 tclark tclark 24 Aug 18 2004
.bash_logout
-rw-r--r-- 1 tclark tclark 191 Aug 18 2004
.bash_profile
-rw-r--r-- 1 tclark tclark 124 Aug 18 2004
.bashrc
-rw-r--r-- 1 tclark tclark 237 May 22 2003
.emacs
-rw-r--r-- 1 tclark tclark 220 Nov 27 2002
.zshrc
drwxr-xr-x 3 tclark tclark 4096 Aug 12 2002
.kde
If instead we want to add on to the end of a file the >>
symbol can be used. Here we are placing the current time at the end of the
time.txt file then examining the file with cat:
$ date >> time.txt
$ date >> time.txt
$ date >> time.txt
$ cat time.txt
Thu Feb 24 23:31:22 MST
2005
Thu Feb 24 23:31:36 MST 2005
Thu Feb 24 23:31:50 MST 2005
Here is how a file can be redirected into a command. In
this case we're using the dir.lst file from the example above.
$ less < dir.lst
total 68
drwx------ 4 tclark tclark 4096 Feb 24 23:27
.
-rw-rw-r-- 1 tclark tclark 0 Feb 24 23:27
dir.lst
-rw------- 1 tclark tclark 11629 Feb 24 21:24
.bash_history
-rwxrwxr-x 1 tclark tclark 325 Feb 24 21:17
mylogin
-rw------- 1 tclark tclark 4151 Feb 24 21:17
.viminfo
-rwxrwxr-x 1 tclark tclark 208 Feb 19 22:52
test.bsh
drwxrwxr-x 2 tclark authors 4096 Feb 3 23:11
examples
-rw-rw-r-- 1 tclark tclark 0 Feb 3 09:00
example1.fil
-rw-r--r-- 1 tclark authors 0 Jan 27 00:22
umask_example.fil
drwxr-xr-x 8 root root 4096 Jan 25 22:16
..
-rw-rw-r-- 1 tclark tclark 0 Jan 13 21:13
example2.xxx
-rw-r--r-- 1 tclark tclark 120 Aug 24 2004
.gtkrc
-rw-r--r-- 1 tclark tclark 24 Aug 18 2004
.bash_logout
-rw-r--r-- 1 tclark tclark 191 Aug 18 2004
.bash_profile
-rw-r--r-- 1 tclark tclark 124 Aug 18 2004
.bashrc
-rw-r--r-- 1 tclark tclark 237 May 22 2003
.emacs
-rw-r--r-- 1 tclark tclark 220 Nov 27 2002
.zshrc
drwxr-xr-x 3 tclark tclark 4096 Aug 12 2002
.kde
(END)
Sometimes we want to cut out the middle man, avoid using
files, and redirect output directly from one command to another. That's where
the pipe comes in.
Pipes
The pipe can be used to pass the output from one command
or program to another command or program without creating an intermediate file.
The use of pipes is a convenient way to string together multiple commands on a
command line. The pipe symbol is the vertical bar (|), which is placed between
commands to invoke a pipe.
To see the files in the current working directory that
have .fil as the file name extension, a pipe could be formed between the ls and
grep commands as follows:
$ ls -l|grep .fil
-rw-rw-r-- 1 tclark tclark 0 Feb 3 09:00
example1.fil
-rw-r--r-- 1 tclark authors 0 Jan 27 00:22
umask_example.fil
It's important to note that the grep command here is not
only looking at the file name but is actually looking for the string .fil
anywhere in the lines of the ls ?l output.
The following more complicated pipe example show the
current processes (ps ?ef), redirects the list of processes to filter for only
ones with root in the output (grep root), and counts the number of remaining
lines with the word count command (wc ?l). The resulting string of commands
returns the total number of current root processes.
$ ps -ef|grep root|wc -l
38
This shows how pipes can be used to combine multiple
commands to get some fairly sophisticated results.
This is an excerpt from "Easy
Linux Commands" by Linux guru Jon Emmons. You can purchase it for only
$19.95 (30%-off) at
this link.