533 lines
8.6 KiB
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 <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<&0 # Link file descriptor #6 with stdin.
|
|
# Saves stdin.
|
|
|
|
exec < 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<&6 6<&-
|
|
# Now restore stdin from fd #6, where it had been saved,
|
|
#+ and close fd #6 ( 6<&- ) to free it for other processes to use.
|
|
#
|
|
# <&6 6<&- 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 >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 > 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 > 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>&1 # Link file descriptor #6 with stdout.
|
|
# Saves stdout.
|
|
|
|
exec > $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>&6 6>&- # 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<&0
|
|
exec < $1 # Will read from input file.
|
|
|
|
exec 7>&1
|
|
exec > $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>&7 7>&- # Restore stout.
|
|
exec 0<&4 4<&- # 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<> myfile.txt
|
|
while read line <&3
|
|
do {
|
|
echo "$line"
|
|
(( Lines++ )); # Incremented values of this variable
|
|
#+ accessible outside loop.
|
|
# No subshell, no problem.
|
|
}
|
|
done
|
|
exec 3>&-
|
|
|
|
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
|
|
> |