📄 io-redirection.html
字号:
> </P><P>For a more detailed introduction to I/O redirection see <AHREF="ioredirintro.html">Appendix E</A>.</P><DIVCLASS="SECT1"><H1CLASS="SECT1"><ANAME="AEN16560"></A>19.1. Using <ICLASS="FIRSTTERM">exec</I></H1><P><ANAME="USINGEXECREF"></A></P><P>An <BCLASS="COMMAND">exec <filename</B> command redirects <TTCLASS="FILENAME">stdin</TT> to a file. From that point on, all <TTCLASS="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 <AHREF="sedawk.html#SEDREF">sed</A> and/or <AHREF="awk.html#AWKREF">awk</A>.</P><DIVCLASS="EXAMPLE"><HR><ANAME="REDIR1"></A><P><B>Example 19-1. Redirecting <TTCLASS="FILENAME">stdin</TT> using <ICLASS="FIRSTTERM">exec</I></B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # Redirecting stdin using 'exec'. 3 4 5 exec 6<&0 # Link file descriptor #6 with stdin. 6 # Saves stdin. 7 8 exec < data-file # stdin replaced by file "data-file" 9 10 read a1 # Reads first line of file "data-file". 11 read a2 # Reads second line of file "data-file." 12 13 echo 14 echo "Following lines read from file." 15 echo "-------------------------------" 16 echo $a1 17 echo $a2 18 19 echo; echo; echo 20 21 exec 0<&6 6<&- 22 # Now restore stdin from fd #6, where it had been saved, 23 #+ and close fd #6 ( 6<&- ) to free it for other processes to use. 24 # 25 # <&6 6<&- also works. 26 27 echo -n "Enter data " 28 read b1 # Now "read" functions as expected, reading from normal stdin. 29 echo "Input read from stdin." 30 echo "----------------------" 31 echo "b1 = $b1" 32 33 echo 34 35 exit 0</PRE></TD></TR></TABLE><HR></DIV><P>Similarly, an <BCLASS="COMMAND">exec >filename</B> command redirects <TTCLASS="FILENAME">stdout</TT> to a designated file. This sends all command output that would normally go to <TTCLASS="FILENAME">stdout</TT> to that file.</P><DIVCLASS="IMPORTANT"><TABLECLASS="IMPORTANT"WIDTH="100%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="common/important.png"HSPACE="5"ALT="Important"></TD><TDALIGN="LEFT"VALIGN="TOP"><P> <BCLASS="COMMAND">exec N > filename</B> affects the entire script or <ICLASS="FIRSTTERM">current shell</I>. Redirection in the <AHREF="special-chars.html#PROCESSIDREF">PID</A> of the script or shell from that point on has changed. However . . . </P><P> <BCLASS="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><DIVCLASS="EXAMPLE"><HR><ANAME="REASSIGNSTDOUT"></A><P><B>Example 19-2. Redirecting <TTCLASS="FILENAME">stdout</TT> using <ICLASS="FIRSTTERM">exec</I></B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # reassign-stdout.sh 3 4 LOGFILE=logfile.txt 5 6 exec 6>&1 # Link file descriptor #6 with stdout. 7 # Saves stdout. 8 9 exec > $LOGFILE # stdout replaced with file "logfile.txt". 10 11 # ----------------------------------------------------------- # 12 # All output from commands in this block sent to file $LOGFILE. 13 14 echo -n "Logfile: " 15 date 16 echo "-------------------------------------" 17 echo 18 19 echo "Output of \"ls -al\" command" 20 echo 21 ls -al 22 echo; echo 23 echo "Output of \"df\" command" 24 echo 25 df 26 27 # ----------------------------------------------------------- # 28 29 exec 1>&6 6>&- # Restore stdout and close file descriptor #6. 30 31 echo 32 echo "== stdout now restored to default == " 33 echo 34 ls -al 35 echo 36 37 exit 0</PRE></TD></TR></TABLE><HR></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="UPPERCONV"></A><P><B>Example 19-3. Redirecting both <TTCLASS="FILENAME">stdin</TT> and <TTCLASS="FILENAME">stdout</TT> in the same script with <ICLASS="FIRSTTERM">exec</I></B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # upperconv.sh 3 # Converts a specified input file to uppercase. 4 5 E_FILE_ACCESS=70 6 E_WRONG_ARGS=71 7 8 if [ ! -r "$1" ] # Is specified input file readable? 9 then 10 echo "Can't read from input file!" 11 echo "Usage: $0 input-file output-file" 12 exit $E_FILE_ACCESS 13 fi # Will exit with same error 14 #+ even if input file ($1) not specified (why?). 15 16 if [ -z "$2" ] 17 then 18 echo "Need to specify output file." 19 echo "Usage: $0 input-file output-file" 20 exit $E_WRONG_ARGS 21 fi 22 23 24 exec 4<&0 25 exec < $1 # Will read from input file. 26 27 exec 7>&1 28 exec > $2 # Will write to output file. 29 # Assumes output file writable (add check?). 30 31 # ----------------------------------------------- 32 cat - | tr a-z A-Z # Uppercase conversion. 33 # ^^^^^ # Reads from stdin. 34 # ^^^^^^^^^^ # Writes to stdout. 35 # However, both stdin and stdout were redirected. 36 # Note that the 'cat' can be omitted. 37 # ----------------------------------------------- 38 39 exec 1>&7 7>&- # Restore stout. 40 exec 0<&4 4<&- # Restore stdin. 41 42 # After restoration, the following line prints to stdout as expected. 43 echo "File \"$1\" written to \"$2\" as uppercase conversion." 44 45 exit 0</PRE></TD></TR></TABLE><HR></DIV><P>I/O redirection is a clever way of avoiding the dreaded <AHREF="subshells.html#PARVIS">inaccessible variables within a subshell</A> problem.</P><DIVCLASS="EXAMPLE"><HR><ANAME="AVOIDSUBSHELL"></A><P><B>Example 19-4. Avoiding a subshell</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # avoid-subshell.sh 3 # Suggested by Matthew Walker. 4 5 Lines=0 6 7 echo 8 9 cat myfile.txt | while read line; 10 do { 11 echo $line 12 (( Lines++ )); # Incremented values of this variable 13 #+ inaccessible outside loop. 14 # Subshell problem. 15 } 16 done 17 18 echo "Number of lines read = $Lines" # 0 19 # Wrong! 20 21 echo "------------------------" 22 23 24 exec 3<> myfile.txt 25 while read line <&3 26 do { 27 echo "$line" 28 (( Lines++ )); # Incremented values of this variable 29 #+ accessible outside loop. 30 # No subshell, no problem. 31 } 32 done 33 exec 3>&- 34 35 echo "Number of lines read = $Lines" # 8 36 37 echo 38 39 exit 0 40 41 # Lines below not seen by script. 42 43 $ cat myfile.txt 44 45 Line 1. 46 Line 2. 47 Line 3. 48 Line 4. 49 Line 5. 50 Line 6. 51 Line 7. 52 Line 8.</PRE></TD></TR></TABLE><HR></DIV></DIV></DIV><H3CLASS="FOOTNOTES">Notes</H3><TABLEBORDER="0"CLASS="FOOTNOTES"WIDTH="100%"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="5%"><ANAME="FTN.AEN16482"HREF="io-redirection.html#AEN16482">[1]</A></TD><TDALIGN="LEFT"VALIGN="TOP"WIDTH="95%"><P><ANAME="FDREF1"></A>A <ICLASS="FIRSTTERM">file descriptor</I> is simply a number that the operating system assigns to an open file to keep track of it. Consider it a simplified type of file pointer. It is analogous to a <ICLASS="FIRSTTERM">file handle</I> in <ICLASS="FIRSTTERM">C</I>.</P></TD></TR><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="5%"><ANAME="FTN.AEN16494"HREF="io-redirection.html#AEN16494">[2]</A></TD><TDALIGN="LEFT"VALIGN="TOP"WIDTH="95%"><P>Using <TTCLASS="REPLACEABLE"><I>file descriptor 5</I></TT> might cause problems. When Bash creates a child process, as with <AHREF="internal.html#EXECREF">exec</A>, the child inherits fd 5 (see Chet Ramey's archived e-mail, <AHREF="http://www.geocrawler.com/archives/3/342/1996/1/0/1939805/"TARGET="_top"> SUBJECT: RE: File descriptor 5 is held open</A>). Best leave this particular fd alone.</P></TD></TR></TABLE><DIVCLASS="NAVFOOTER"><HRALIGN="LEFT"WIDTH="100%"><TABLESUMMARY="Footer navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top"><AHREF="here-docs.html"ACCESSKEY="P">Prev</A></TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="index.html"ACCESSKEY="H">Home</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top"><AHREF="redircb.html"ACCESSKEY="N">Next</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">Here Documents</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="part5.html"ACCESSKEY="U">Up</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">Redirecting Code Blocks</TD></TR></TABLE></DIV></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -