old-www/LDP/abs/html/x17974.html

533 lines
8.6 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML
><HEAD
><TITLE
>Using exec</TITLE
><META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK
REL="HOME"
TITLE="Advanced Bash-Scripting Guide"
HREF="index.html"><LINK
REL="UP"
TITLE="I/O Redirection"
HREF="io-redirection.html"><LINK
REL="PREVIOUS"
TITLE="I/O Redirection"
HREF="io-redirection.html"><LINK
REL="NEXT"
TITLE="Redirecting Code Blocks"
HREF="redircb.html"></HEAD
><BODY
CLASS="SECT1"
BGCOLOR="#FFFFFF"
TEXT="#000000"
LINK="#0000FF"
VLINK="#840084"
ALINK="#0000FF"
><DIV
CLASS="NAVHEADER"
><TABLE
SUMMARY="Header navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>Advanced Bash-Scripting Guide: </TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="io-redirection.html"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
>Chapter 20. I/O Redirection</TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="redircb.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><DIV
CLASS="SECT1"
><H1
CLASS="SECT1"
><A
NAME="AEN17974"
></A
>20.1. Using <I
CLASS="FIRSTTERM"
>exec</I
></H1
><P
><A
NAME="USINGEXECREF"
></A
></P
><P
>An <B
CLASS="COMMAND"
>exec &#60;filename</B
> command redirects
<TT
CLASS="FILENAME"
>stdin</TT
> to a file. From that point on, all
<TT
CLASS="FILENAME"
>stdin</TT
> comes from that file, rather than
its normal source (usually keyboard input). This provides a
method of reading a file line by line and possibly parsing
each line of input using <A
HREF="sedawk.html#SEDREF"
>sed</A
>
and/or <A
HREF="awk.html#AWKREF"
>awk</A
>.</P
><DIV
CLASS="EXAMPLE"
><A
NAME="REDIR1"
></A
><P
><B
>Example 20-1. Redirecting <TT
CLASS="FILENAME"
>stdin</TT
> using
<I
CLASS="FIRSTTERM"
>exec</I
></B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>#!/bin/bash
# Redirecting stdin using 'exec'.
exec 6&#60;&#38;0 # Link file descriptor #6 with stdin.
# Saves stdin.
exec &#60; data-file # stdin replaced by file "data-file"
read a1 # Reads first line of file "data-file".
read a2 # Reads second line of file "data-file."
echo
echo "Following lines read from file."
echo "-------------------------------"
echo $a1
echo $a2
echo; echo; echo
exec 0&#60;&#38;6 6&#60;&#38;-
# Now restore stdin from fd #6, where it had been saved,
#+ and close fd #6 ( 6&#60;&#38;- ) to free it for other processes to use.
#
# &#60;&#38;6 6&#60;&#38;- also works.
echo -n "Enter data "
read b1 # Now "read" functions as expected, reading from normal stdin.
echo "Input read from stdin."
echo "----------------------"
echo "b1 = $b1"
echo
exit 0</PRE
></FONT
></TD
></TR
></TABLE
></DIV
><P
>Similarly, an <B
CLASS="COMMAND"
>exec &#62;filename</B
>
command redirects <TT
CLASS="FILENAME"
>stdout</TT
> to a designated
file. This sends all command output that would normally go
to <TT
CLASS="FILENAME"
>stdout</TT
> to that file.</P
><DIV
CLASS="IMPORTANT"
><P
></P
><TABLE
CLASS="IMPORTANT"
WIDTH="100%"
BORDER="0"
><TR
><TD
WIDTH="25"
ALIGN="CENTER"
VALIGN="TOP"
><IMG
SRC="../images/important.gif"
HSPACE="5"
ALT="Important"></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
><P
> <B
CLASS="COMMAND"
>exec N &#62; filename</B
> affects the entire
script or <I
CLASS="FIRSTTERM"
>current shell</I
>. Redirection in
the <A
HREF="special-chars.html#PROCESSIDREF"
>PID</A
> of the script or shell
from that point on has changed. However . . .
</P
><P
> <B
CLASS="COMMAND"
>N &#62; filename</B
> affects only the newly-forked process,
not the entire script or shell.
</P
><P
>Thank you, Ahmed Darwish, for pointing this out.</P
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="EXAMPLE"
><A
NAME="REASSIGNSTDOUT"
></A
><P
><B
>Example 20-2. Redirecting <TT
CLASS="FILENAME"
>stdout</TT
> using
<I
CLASS="FIRSTTERM"
>exec</I
></B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>#!/bin/bash
# reassign-stdout.sh
LOGFILE=logfile.txt
exec 6&#62;&#38;1 # Link file descriptor #6 with stdout.
# Saves stdout.
exec &#62; $LOGFILE # stdout replaced with file "logfile.txt".
# ----------------------------------------------------------- #
# All output from commands in this block sent to file $LOGFILE.
echo -n "Logfile: "
date
echo "-------------------------------------"
echo
echo "Output of \"ls -al\" command"
echo
ls -al
echo; echo
echo "Output of \"df\" command"
echo
df
# ----------------------------------------------------------- #
exec 1&#62;&#38;6 6&#62;&#38;- # Restore stdout and close file descriptor #6.
echo
echo "== stdout now restored to default == "
echo
ls -al
echo
exit 0</PRE
></FONT
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="EXAMPLE"
><A
NAME="UPPERCONV"
></A
><P
><B
>Example 20-3. Redirecting both <TT
CLASS="FILENAME"
>stdin</TT
> and
<TT
CLASS="FILENAME"
>stdout</TT
> in the same script with
<I
CLASS="FIRSTTERM"
>exec</I
></B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>#!/bin/bash
# upperconv.sh
# Converts a specified input file to uppercase.
E_FILE_ACCESS=70
E_WRONG_ARGS=71
if [ ! -r "$1" ] # Is specified input file readable?
then
echo "Can't read from input file!"
echo "Usage: $0 input-file output-file"
exit $E_FILE_ACCESS
fi # Will exit with same error
#+ even if input file ($1) not specified (why?).
if [ -z "$2" ]
then
echo "Need to specify output file."
echo "Usage: $0 input-file output-file"
exit $E_WRONG_ARGS
fi
exec 4&#60;&#38;0
exec &#60; $1 # Will read from input file.
exec 7&#62;&#38;1
exec &#62; $2 # Will write to output file.
# Assumes output file writable (add check?).
# -----------------------------------------------
cat - | tr a-z A-Z # Uppercase conversion.
# ^^^^^ # Reads from stdin.
# ^^^^^^^^^^ # Writes to stdout.
# However, both stdin and stdout were redirected.
# Note that the 'cat' can be omitted.
# -----------------------------------------------
exec 1&#62;&#38;7 7&#62;&#38;- # Restore stout.
exec 0&#60;&#38;4 4&#60;&#38;- # Restore stdin.
# After restoration, the following line prints to stdout as expected.
echo "File \"$1\" written to \"$2\" as uppercase conversion."
exit 0</PRE
></FONT
></TD
></TR
></TABLE
></DIV
><P
>I/O redirection is a clever way of avoiding the dreaded <A
HREF="subshells.html#PARVIS"
>inaccessible variables within a subshell</A
>
problem.</P
><DIV
CLASS="EXAMPLE"
><A
NAME="AVOIDSUBSHELL"
></A
><P
><B
>Example 20-4. Avoiding a subshell</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>#!/bin/bash
# avoid-subshell.sh
# Suggested by Matthew Walker.
Lines=0
echo
cat myfile.txt | while read line;
do {
echo $line
(( Lines++ )); # Incremented values of this variable
#+ inaccessible outside loop.
# Subshell problem.
}
done
echo "Number of lines read = $Lines" # 0
# Wrong!
echo "------------------------"
exec 3&#60;&#62; myfile.txt
while read line &#60;&#38;3
do {
echo "$line"
(( Lines++ )); # Incremented values of this variable
#+ accessible outside loop.
# No subshell, no problem.
}
done
exec 3&#62;&#38;-
echo "Number of lines read = $Lines" # 8
echo
exit 0
# Lines below not seen by script.
$ cat myfile.txt
Line 1.
Line 2.
Line 3.
Line 4.
Line 5.
Line 6.
Line 7.
Line 8.</PRE
></FONT
></TD
></TR
></TABLE
></DIV
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
SUMMARY="Footer navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="io-redirection.html"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="index.html"
ACCESSKEY="H"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="redircb.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>I/O Redirection</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="io-redirection.html"
ACCESSKEY="U"
>Up</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Redirecting Code Blocks</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>