Chapter 16. I/O redirection
By default, three "Files" are always open,(Keyboard ),(Screen), and(Error messages are output to the screen ). these three files and other open files can be redirected. A simple explanation of redirection is to capture a file, command, program, script, or even a code block in the script (see example 3-1
And
Example 3-2), and then send the output as input to another file, command, program, or script.
Each opened file is assigned a file descriptor. [1],, AndThe file descriptors are 0, 1, and 2 respectively. For the extra files being opened, the descriptors 3 to 9 are retained. In some cases, these extra file descriptors are allocated to stdin,
Stdout, or stderr, is very useful as a temporary copy link. [2] After complex redirection and refresh, they need to be restored to normal (see
Example 16-1 ).
1 command_output> 2 # redirect stdout to a file. 3 # if this file is not available, it will be created, otherwise it will be overwritten. 4 5 LS-LR> dir-tree.list 6 # create a file that contains the directory tree list. 7 8:> filename 9 #> the file "FILENAME" is truncated to 0 length. 10 # If the file does not exist, create a zero-length file (same effect as 'touch ). 11 #: it is a placeholder and does not produce any output. 12 13> filename 14 #> the file "FILENAME" is truncated to 0. 15 # If the file does not exist, create a zero-length file (same effect as 'touch ). 16 # (same effect as ":>" above, but may not work in some shells .) 17 18 command_output> 19 # redirect stdout to a file. 20 # If the file does not exist, create it. If yes, append it to the end of the file. 21 22 23 # single-line redirection command (will only affect the row where they are located): 24 # -------------------------------------------------------------- 25 26 1> filename 27 # redirect stdout to the file ". 28 1> filename 29 # redirect and append stdout to the file "FILENAME ". 30 2> filename 31 # redirect stderr to the file "FILENAME ". 32 2> filename 33 # redirect and append stderr to the file "FILENAME ". 34 &> filename 35 # redirect both stdout and stderr to the file "FILENAME ". 36 37 #=================================================== ========================================================== = 38 # stdout redirection, one row at a time. 39 logfile = script. log 40 41 echo "This statement is sent to the log file, \" $ logfile \". "1> $ logfile 42 echo" This statement is appended to \ "$ logfile \". "1> $ logfile 43 echo" This statement is also appended to \ "$ logfile \". "1> $ logfile 44 echo" This statement is echoed to stdout, and will not appear in \ "$ logfile \". "45 # after each line, these redirection commands will automatically" reset ". 46 47 48 49 # redirect stderr, one row at a time. 50 errorfile = script. errors 51 52 bad_command1 2> $ errorfile # the error message is sent to $ errorfile. 53 bad_command2 2> $ errorfile # Add the error message to $ errorfile. 54 bad_command3 # the error message is echo to stderr, 55 # + and does not appear in $ errorfile. 56 # after each line, these redirection commands will automatically "reset ". 57 #=================================================== ========================================================== 58 59 60 61 2> & 1 62 # redirect stderr to stdout. 63 # the error message is sent to a place like stdout. 64 65 I> & J 66 # redirection file descriptorIToJ. 67 # pointIAll output of the file is sentJGo to. 68 69> & J 70 # default, redirection file descriptor1(Stdout)J. 71 # all outputs passed to stdout are deliveredJ. 72 73 0 <FILENAME 74 <FILENAME 75 # accept input from the file. 76 # It is a paired command with ">" and is usually used in combination. 77 #78 # grep search-word <FILENAME 79 80 81 [J] <> filename 82 # open the file "FILENAME" to read and write "FILENAME, and assign the file descriptor "J" to it. 83 # If the file "FILENAME" does not exist, create it. 84 # If the file descriptor "J" is not specified, the default value is fd 0 and stdin. 85 #86 # this type of application is usually used to write to a specified place in a file. 87 echo 1234567890> file # Write the string to "File ". 88 exec 3 <> file # Open "file" and assign it FD 3. 89 read-N 4 <& 3 # Read-Only 4 characters. 90 echo-N.> & 3 # Write a decimal point. 91 exec 3> &-# disable FD 3. 92 cat file #=> 1234.67890 93 # Random storage. 94 95 96 97 | 98 # MPs queue. 99 # general purpose processing and command chain tools. 100 # similar to ">", but more common. 101 # It is useful for concatenating commands, scripts, files, and programs. 102 cat *. TXT | sort | uniq> result-file 103 # Sort the output of all. txt files and delete duplicate rows. 104 # Save the result to "result-File. |
You can combine multiple instances of the input/output redirection and (or) pipeline to write them on one row.
1 command < input-file > output-file 2 3 command1 | command2 | command3 > output-file |
See
Example 12-28 and
Example A-15.
You can redirect multiple output streams to one file.
1 LS-YZ> command. log 2> & 1 2 # Put the result of the incorrect option "YZ" to the file "command. log. 3 # Because stderr is redirected to this file, 4 # + all error messages will point to it. 5 6 # note that the following example will not give the same result. 7 LS-YZ 2> & 1> command. log 8 # output an error message, but it is not written to the file. 9 10 # If both stdout and stderr are redirected, the order of the 11 # + command will be somewhat different. |
Disable file descriptor
-
N <&-
-
Disable input file descriptorN.
-
0 <&-, <&-
-
Close.
-
N> &-
-
Disable output file descriptor.
-
1> &-,> &-
-
Close.
The sub-process inherits the opened file descriptor. This is why the pipeline can work. If you want to prevent FD from being inherited, you can turn it off.
1 # Only redirect stderr to one pipeline. 2 3 exec 3> & 1 # Save the "value" of the current stdout ". 4 Ls-L 2> & 1> & 3 3> &-| grep bad 3> &-# disable FD 3 for 'grep' (but not 'LS '). 5 # ^ 6 exec 3> &-# disable the remaining scripts. 7 8 # Thanks, S. c. |
For more information about I/O redirection, see
Appendix E.
16.1. Use Exec
Exec <FILENAMEThe command redirects stdin to the file. from this sentence, all the input is from this file, rather than the standard input (usually keyboard input ). this provides a method for reading files by row, and you can use SED and/or awk to analyze each row.
Example 16-1. UseExec redirection standard input
1 #! /Bin/bash 2 # Use 'exec 'to redirect standard input. 3 4 5 exec 6 <& 0 # Link file descriptor #6 with stdin. 6 # Save stdin. 7 8 exec <data-file # stdin is replaced by the file "data-file. 9 10 read A1 # read the first line of the file "data-file. 11 read A2 # Read the second line of the 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, because we just redirected stdin to #6, 23 # + and then disable FD #6 (6 <&-) so that this descriptor can continue to be used by other processes. 24 #25 # <& 6 6 <&-you can do this. 26 27 echo-n "Enter data" 28 read B1 # Now "read" is back to normal, that is, reading from stdin. 29 echo "input read from stdin. "30 echo" ---------------------- "31 echo" b1 = $ B1 "32 33 echo 34 35 exit 0 |
Similarly,Exec> filenameThe command will redirect stdout to a specified file, so that all command output will be sent to the specified file, instead of stdout.
Example 16-2. Use exec to redirect stdout
1 #! /Bin/bash 2 # reassign-stdout.sh 3 4 logfile.txt 5 6 exec 6> & 1 # connect FD #6 to stdout. 7 # Save stdout. 8 9 exec> $ logfile # stdout is replaced by the "logfile.txt" file. 10 11 # --------------------------------------------------------- #12 # the output of all commands in this section is sent to the 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> &-# restore stdout, disable the file descriptor #6. 30 31 echo 32 echo "= stdout now restored to default =" 33 echo 34 LS-Al 35 echo 36 37 exit 0 |
Example 16-3. Use exec to redirect stdin and stdout in the same script
1 #! /Bin/bash 2 # upperconv. SH 3 # convert a specified input file to uppercase. 4 5 e_file_access = 70 6 e_wrong_args = 71 7 8 if [! -R "$1"] # determines whether the specified input file is 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 # Even if the input file ($1) if 14 # + is not specified, it will still exit with the same error (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 be read from the input file. 26 27 exec 7> & 1 28 exec> $2 # write it to the output file. 29 # assume that the output file is writable (add check ?). 30 31 # --------------------------------------------- 32 CAT-| tr a-Z A-Z # convert to uppercase. 33 # ^ # Read from stdin. reads from stdin. 34 # ^ # Write to stdout. 35 # However, stdin and stdout are all redirected. 36 # --------------------------------------------- 37 38 exec 1> & 7 7> &-# restore stout. 39 exec 0 <& 4 4 <&-# restore stdin. 40 41 # After recovery, the following line of code will be printed to stdout as expected. 42 echo "file \" $1 \ "written to \" $2 \ "as uppercase conversion. "43 44 exit 0 |
I/O redirection is a way to avoid the terrible issue of unaccessable variables in sub-shells.
Example 16-4. Avoid subshell
1 #! /Bin/bash 2 # avoid-subshell.sh 3 # advice from Matthew Walker. 4 5 lines = 0 6 7 Echo 8 9 CAT myfile.txt | while read line; # (Note: pipelines generate sub-shells) 10 do {11 echo $ line 12 (lines ++); # increase the value of this variable to 13 # +, but the External Loop cannot be accessed. 14 # subshell Problems. 15} 16 done 17 18 echo "number of lines read = $ lines" #0 19 # error! 20 21 echo "----------------------" 22 23 24 exec 3 <> myfile.txt 25 while read line <& 3 26 do {27 echo "$ line" 28 (lines ++ )); # Add the variable value 29 # + now the external loop can be accessed. 30 # No sub-shell, now it's okay. 31} 32 done 33 exec 3> &-34 35 echo "number of lines read = $ lines" #8 36 37 echo 38 39 exit 0 40 41 # The following rows are scripts result, the script will not come here. 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. |
|
Note:
[1] |
OneFile descriptorTo put it bluntly, the file system assigns a number to the file to track the opened file. It can also be understood as a simple version of the file pointer.File handleSimilar concepts. |
[2] |
UseFile descriptor5 May cause problems. When bash uses exec to create a sub-process, the sub-process will inherit fd5 (see archive e-mail, subject of Chet Ramey: Re: file descriptor 5 is held open). It is best not to provoke this specific FD. |