Input and Output

When you write shell scripts, you want to be able to obtain input from sources outside your scripts; for example, from another file or from keyboard input. You also want to be able to generate output both for use within the script and for display on-screen.

The following sections describe how to control input and output of a shell script, using standard input, output, error, and redirection; how to accept user input (input from the keyboard) to a script; how to create “here” documents; and how to generate output to the screen.

Standard In, Standard Out, and Standard Error

When writing shell scripts, you can control input/output redirection. Input redirection forces a command to read any necessary input from a file instead of from the keyboard. Output redirection sends the output from a command into a file or pipe instead of to the screen.

Each process created by a shell script begins with three file descriptors associated with it, as shown in Figure 76.

Figure 76. File Descriptors


These file descriptors—standard input, standard output, and standard error—determine where input to the process comes from and where the output and error messages are sent.

Standard input (STDIN) is always file descriptor 0. Standard input is the place where the shell looks for its input data. Usually data for standard input comes from the keyboard. You can specify standard input to come from another source with input/output redirection.

Standard output (STDOUT) is always file descriptor 1. Standard output (default) is the place where the results of the execution of the program are sent. Usually, the results of program execution are displayed on the terminal screen. You can redirect standard output to a file or suppress it completely by redirecting it to /dev/null.

Standard error (STDERR) is always file descriptor 2. Standard error is the place where error messages are sent as they are generated during command processing. Usually, error messages are displayed on the terminal screen. You can redirect standard error to a file or suppress it completely by redirecting it to /dev/null.

You can use the file descriptor numbers 0 (standard input), 1 (standard output), and 2 (standard error) together with the redirection metacharacters to control input and output in the Bourne and Korn shells. Table 86 shows the common ways you can redirect file descriptors.

Table 86. Bourne and Korn Shell Redirection
Command Description
<file, or 0<file Take STDIN from file.
> file, or 1> file Redirect STDOUT to file.
2> file Redirect STDERR to file.
>> file Append STDOUT to end of file.
2>&1 Redirect STDERR to the location where STDOUT is currently directed.
cmd1 | cmd2 Pipe standard output of cmd1 as standard input to cmd2.
<> file Use file as both STDIN and STDOUT.
<&- Close STDIN.
>&- Close STDOUT.
2>&- Close STDERR.

When redirecting STDIN and STDOUT in the Bourne and Korn shells, you can omit the file descriptors 0 and 1 from the redirection symbols. You must always use the file descriptor 2 with the redirection symbol to denote STDERR.

The 0 and 1 file descriptors are implied and not used explicitly for the C shell, as shown in Table 87. The C shell representation for standard error (2) is an ampersand (&). STDERR can only be redirected when redirecting STDOUT.

Table 87. C Shell Redirection
Command Description
> file Redirect STDOUT to file.
< file Take input from file.
>> file Append STDOUT to end of file.
>& file Redirect STDOUT and STDERR to file.
>>& file Append STDOUT and STDERR to file.
2>&- Close STDERR.

Command-Line Input

You can ask users to provide input to a script as part of the command-line argument when the script is run. All three shells use the positional parameter $n to specify as many as nine command-line arguments (for example, $1, $2, $3, up to $9). $0 is a legitimate variable; it returns the name of the command.

You can use each of these command-line arguments to pass file names or other information into a shell script from a command line.

Bourne Shell Command-Line Input

The following Bourne shell script, named tryit, returns the number of command-line arguments and echoes each argument.

#!/bin/sh

echo $#
for var in $*
do
        echo $var
done

The following example shows the output for seven command-line arguments.

$ tryit one two three four five six seven
7
one
two
three
four
five
six
seven
$

Instead of using $#, the following example uses echo $0 (which displays the name of the script) and echo $1, echo $2, and echo $3 to display up to three command-line arguments.

#!/bin/sh

echo $0
echo $1
echo $2
echo $3

The following example provides four command-line arguments, but the tryit script processes only three of those arguments. The echo$0 line echoes the name of the script.

$ tryit one two three four
tryit
one
two
three
$

NOTE

The $n notation does not return an error if no parameters are provided as part of the command. Users do not need to supply command-line arguments, so you cannot be sure that $n will contain a value unless you check the number of positional parameters with $# for the Bourne and Korn shells.


Korn Shell Command-Line Input

The scripts shown in “Bourne Shell Command-Line Input,” above, also work with the Korn shell. In addition, with the Korn shell, you can use ${10}, ${11}...notation to recognize more than the nine command-line arguments permitted by the $1...$9 syntax.

C Shell Command-Line Input

For the C shell, instead of the echo $# statement shown in the first example in “Bourne Shell Command-Line Input”, use $#argv to hold the number of command-line arguments.

The C shell provides additional syntax for positional parameters, as shown in Table 88.

Table 88. C Shell $argv Notation
Notation Description
$#argv $* Count the number of command-line arguments.
$argv Return the value of all arguments.
$argv[1-3] Return the value of arguments 1 through 3.
$0 Return the command used to run the shell script.
$argv[n] Return the nth argument.
$argv[$#argv} Return the last argument.

The shell performs range checking on the $argv[n] syntax, but it does not on the $n syntax. If the shell does not find the word, you get the message Subscript out of range.

NOTE

$argv[0] is not defined and does not return the name of the script.


The following example script shows different ways you can use the argv syntax.

#!/bin/csh -f
echo Number of args = $#argv
echo All args = $*
echo All args = $argv
echo Args 1-3 = $argv[1-3]
echo Name of script file = $0
echo Script file? = $argv[0]
echo Second arg = $argv[2]
echo Last arg = $argv[$#argv]
echo Fifth arg = $5
echo Fifth arg = $argv[5]

The following example shows the output of the example script. Note that the incorrect $argv[0] argument on the 7th line of the script is ignored and produces no output. The $5 on the 9th line also produces no output because there is no fifth command-line argument.

castle% example one two three four
Number of args = 4
All args = one two three four
All args = one two three four
Args 1-3 = one two three
Name of script file = tryit
Script file? =
Second arg = two
Last arg = four
Fifth arg =
Subscript out of range
castle%

Shifting Command-Line Arguments

You can use the shift command, which is built into all three shells, to manipulate the positional parameters in a script. The shift command moves each argument from $1 through $n to the left, changing the previous argument list. The shift command is particularly useful in processing positional parameters in while loops; you can use these commands together to process each positional parameter in turn.

In the following Bourne shell example, each argument is displayed in turn. The shift command shifts the list to the left, removing the leftmost value in the list, as shown in the following script.

#!/bin/sh
while [ $# -ne 0 ]
do
    echo argument: $1
    shift
done
The following example shows the output of this script:
$ tryit one two three
argument: one
argument: two
argument: three
$

Because the shift command shifts the positional parameters, you need to use $1 in the script only if you want to display (or process) the command-line arguments. The following example shows how to shift positional parameters from a Bourne shell command line.

$ set a b c d e f g h i
$ while [ $# -gt 0 ]; do
> echo $*
> shift
> done
a b c d e f g h i
b c d e f g h i
c d e f g h i
d e f g h i
e f g h i
f g h i
g h i
h i
i
$

Refer to the section “Using while Loops” for more information about while loops.

Interactive Input

You can ask the user to type a single line of input anywhere in a script.

Bourne and Korn Shell Interactive Input

For the Bourne and Korn shells, use the read command followed by a variable name for interactive input.

NOTE

You do not need to assign the variable before you use it as an argument to the read command. The following example shows the Bourne and Korn shell syntax for interactive input.

To suppress the newline at the end of the prompt, use c at the end of the string when /usr/bin is in the path before /usr/ucb. Then, users will type the input on the same line as the string that is displayed. The SunOS 4.x echo -n command works only if you have /usr/ucb in the path before /usr/bin. Otherwise, the script uses the Solaris version of the echo command. Refer to the echo(1) manual page for more information.

Alternatively, you can set the PATH environment variable in the script so that you are assured of getting the version of echo that you want. The script PATH setting overrides the user's PATH settings to make sure the script works as you intended.


#!/bin/sh

echo "Enter search pattern and press Return: c"
read filename

When the prompt is displayed, the script waits for input from the keyboard. When the user types input and presses Return, the input is assigned to the variable and the script continues to execute.

NOTE

Be sure to always include a descriptive screen prompt as part of the script before you request input so that users know that the script is waiting for screen input before it continues.


C Shell Interactive Input

For the C shell, the special variable $< waits for a value from STDIN. You can use $< anywhere you would use a variable.

For the C shell, use $< as a value to a variable, as shown below.

#!/bin/csh -f
echo "Enter search pattern and press Return: c"
set pattern = $<

When the prompt is displayed, the script waits for input from the keyboard. When the user types input and presses Return, the input is assigned to the variable and the script continues to execute.

Here Documents

Sometimes a shell script requires data. Instead of having the data in a file somewhere in the system, you can include the data as part of the shell script. Including the data in the script makes it simpler to distribute and maintain the script. Such a collection of data is called a here document—the data (document) is right here in the shell script. Another advantage of a here document is that shell parameters can be substituted in the document as the shell is reading the data.

The general format of a here document is shown below. The format is the same for all three shells.

							lines of shell commands
   ...
command << delimiter
lines of data belonging
to the here document
delimiter
   ...
   more lines of shell commands
						

The here document operator << signals the beginning of the here document. The operator must be followed by a special string that delimits the input, for example <<DONE. Follow the here document operator with the list of input you want to use. The input can consist of any text and can include variables because the shell does variable substitution on a here document.

NOTE

The shell can perform variable interpolation and substitution, but only if the keyword in the here document has the proper quotes around it. Certain quoting prevents the shell from performing variable substitution. SeeQuotingfor more information about quoting.


At the end of the here document, you must include the delimiter at the left margin on a single line. The shell sends everything between the two delimiters to be processed as standard input.

In the following example, the mail message specified in the here document is sent to members of the staff whose names are contained in a file named stafflist, and invites them to a party. The delimiter used is the string EOF.

#!/bin/sh

time="7:00 p.m."
mail -s "staff party" `cat stafflist` << EOF
Please come to our staff party being held
in the cafeteria at $time tomorrow night
EOF

Output Generation

The following sections describe how to use the echo command, quoting, and command substitution.

NOTE

Although the echo command works in Korn shell scripts, the print command is preferred. The syntax for the print command is the same as for the echo command.


The echo and print Commands

Use the echo command to generate messages to display on a terminal screen. You have already seen some examples of using the echo command to display the value for a variable. You can also use the echo command to display text messages, as shown in the following portion of an interactive Bourne shell script.

#!/bin/sh
echo "Enter a pathname and press Return:"
read pathname

If you want to echo more than one message on the same line, use the c string at the end of the line to leave the cursor at the end of the output line and to suppress the newline. The following example modifies the previous Bourne shell script so that the user types the input following the colon, instead of on the line beneath the prompt message.

#!/bin/sh
echo "Enter a pathname and press Return: c"
read pathname

If you need to display control characters or metacharacters, you can escape them (that is, get the shell to interpret the character literally) by putting a backslash () in front of the character. Refer to the echo(1) manual page for information about special backslash characters (for example, c, ).

The Bourne and Korn shell echo command has fewer restrictions on quoting metacharacters than does the C shell echo command. The following Bourne shell script displays an error message only for the parentheses in the last line, which are not escaped with backslashes. Note that the dollar sign ($) followed by a space does not need to be escaped.

$ more echodemo
#!/bin/sh

echo Type a pathname and press Return:
echo You owe me $35 (Please pay).
echo This is a $ sign (not a variable)
$ echodemo
Type a pathname and press Return:
You owe me $35 (Please pay).
This is a $ sign (Not a variable).
anything: syntax error at line 6: `(' unexpected
$

Quoting

All three shells use the same syntax for quoting, as shown in Table 89. Quoting a string incorrectly can produce many unexpected results.

Table 89. Quoting Characters
Character Term Description
\cellBackslash Backslash Nullify the special meaning of any shell metacharacter, including another backslash.
`` Backquotes Substitute the output of the command enclosed in backquotes as if it were typed in place of the command. Refer to the shell manual pages for more information.
'' Single quotes Nullify the special meaning of all characters except bang (!), the backslash (), and the single quote itself ('). Single quotes are more restrictive than double quotes and do not permit variable or backquote expansion.
"" Double quotes Nullifies the special meaning of all special characters except bang (!), backquote (``), and dollar sign ($). Permits variable and backquote expansion.

NOTE

The bang (!) is not used as a metacharacter in the Bourne and Korn shells. If it is not quoted properly, it is likely to cause problems mostly in the C shell.


The following examples demonstrate the result of different forms of quotation.

$ name=Fred
$ echo "My name is $name"
My name is Fred
$ echo 'My name is $name'
My name is $name
$ echo "Today is `date`"
Today is Tue Oct 31 12:12:35 PDT 2000
$ echo 'Today is `date`'
Today is `date`
$ echo 'Use metacharacters * ? < > | & and $ often'
Use metacharacters * ? < > | & and $ often
$ echo "It's hard to turn off"!
								It's hard to turn off!

Command Substitution

You can substitute the output of the command in place of the command itself. This process is called command substitution. Use backquotes (``) to surround the desired command. You can use command substitution to return the output of the command or to use it as the value for a variable.

NOTE

In the Korn shell, you can use the $(command) syntax instead of backquotes.


In the first example following, the output of the date command is used as part of a larger output string, and the output of the who command is filtered through wc, which counts the number of lines in the output of who to determine how many users are logged in. The second example pipes the output of the who command to the cut command to display only the list of user names and uses the uname -n command to display the name of the system.

$ echo Today is `date` and there are `who | wc -l` users logged in
Today is Wed Feb 14 13:12:41 WST 2001 and there are 5 users logged in

$ echo `who | cut -f1 -d" "` logged in to `uname -n`
winsor newton fred george anna logged in to seachild
$

						

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.233.26