mirror of
https://github.com/rawiriblundell/wiki.bash-hackers.org
synced 2024-11-01 16:43:08 +01:00
217 lines
8.9 KiB
Plaintext
217 lines
8.9 KiB
Plaintext
====== Redirection ======
|
|
|
|
<wrap left todo>Fix me: To be continued</wrap>
|
|
\\
|
|
|
|
Redirection makes it possible to control where the output of a command goes to, and where the input of a command comes from. It's a mighty tool that, together with pipelines, makes the shell powerful. The redirection operators are checked whenever a [[syntax:grammar:parser_exec | simple command is about to be executed]].
|
|
|
|
Under normal circumstances, there are 3 files open, accessible by the file descriptors 0, 1 and 2, all connected to your terminal:
|
|
^Name^FD^Description^
|
|
|''stdin''|0|standard input stream (e.g. keyboard)|
|
|
|''stdout''|1|standard output stream (e.g. monitor)|
|
|
|''stderr''|2|standard error output stream (usually also on monitor)|
|
|
|
|
<wrap center info>The terms "monitor" and "keyboard" refer to the same device, the **terminal** here. Check your preferred UNIX(r)-FAQ for details, I'm too lazy to explain what a terminal is ;-) </wrap>
|
|
|
|
Both, ''stdout'' and ''stderr'' are output file descriptors. Their difference is the **convention** that a program outputs payload on ''stdout'' and diagnostic- and error-messages on ''stderr''. If you write a script that outputs error messages, please make sure you follow this convention!
|
|
|
|
Whenever you **name** such a filedescriptor, i.e. you want to redirect this descriptor, you just use the number:
|
|
<code>
|
|
# this executes the cat-command and redirects its error messages (stderr) to the bit bucket
|
|
cat some_file.txt 2>/dev/null
|
|
</code>
|
|
Whenever you **reference** a descriptor, to point to its current target file, then you use a "''&''" followed by a the descriptor number:
|
|
<code>
|
|
# this executes the echo-command and redirects its normal output (stdout) to the standard error target
|
|
echo "There was an error" 1>&2
|
|
</code>
|
|
|
|
The redirection operation can be **anywhere** in a simple command, so these examples are equivalent:
|
|
<code>
|
|
cat foo.txt bar.txt >new.txt
|
|
cat >new.txt foo.txt bar.txt
|
|
>new.txt cat foo.txt bar.txt
|
|
</code>
|
|
<wrap center important>Every redirection operator takes one or two words as operands. If you have to use operands (e.g. filenames to redirect to) that contain spaces you **must** quote them!</wrap>
|
|
|
|
===== Valid redirection targets and sources =====
|
|
This syntax is recognized whenever a ''TARGET'' or a ''SOURCE'' specification (like below in the details descriptions) is used.
|
|
|
|
^Syntax^Description^
|
|
|''FILENAME''|references a normal, ordinary filename from the filesystem (which can of course be a FIFO, too. Simply everything you can reference in the filesystem)|
|
|
|''&N''|references the current target/source of the filedescriptor ''N'' ("duplicates" the filedescriptor)|
|
|
|''&-''|closes the redirected filedescriptor, useful instead of ''> /dev/null'' constructs (''> &-'')|
|
|
|''/dev/fd/N''|duplicates the filedescriptor ''N'', if ''N'' is a valid integer|
|
|
|''/dev/stdin''|duplicates filedescriptor 0 (''stdin'')|
|
|
|''/dev/stdout''|duplicates filedescriptor 1 (''stdout'')|
|
|
|''/dev/stderr''|duplicates filedescriptor 2 (''stderr'')|
|
|
|''/dev/tcp/HOST/PORT''|assuming ''HOST'' is a valid hostname or IP address, and ''PORT'' is a valid port number or service name: redirect from/to the corresponding TCP socket|
|
|
|''/dev/udp/HOST/PORT''|assuming ''HOST'' is a valid hostname or IP address, and ''PORT'' is a valid port number or service name: redirect from/to the corresponding UDP socket|
|
|
|
|
If a target/source specification fails to open, the whole redirection operation fails. Avoid referencing file descriptors above 9, since you may collide with file descriptors Bash uses internally.
|
|
|
|
|
|
|
|
|
|
===== Redirecting output =====
|
|
<code>
|
|
N > TARGET
|
|
</code>
|
|
|
|
This redirects the file descriptor number ''N'' to the target ''TARGET''. If ''N'' is omitted, ''stdout'' is assumed (FD 1). The ''TARGET'' is **truncated** before writing starts.
|
|
|
|
If the option ''noclobber'' is set with [[commands:builtin:set | the set builtin]], with cause the redirection to fail, when ''TARGET'' names a regular file that already exists. You can manually override that behaviour by forcing overwrite with the redirection operator ''>|'' instead of ''>''.
|
|
|
|
|
|
===== Appending redirected output =====
|
|
<code>
|
|
N >> TARGET
|
|
</code>
|
|
|
|
This redirects the file descriptor number ''N'' to the target ''TARGET''. If ''N'' is omitted, ''stdout'' is assumed (FD 1). The ''TARGET'' is **not truncated** before writing starts.
|
|
|
|
===== Redirecting output and error output =====
|
|
<code>
|
|
&> TARGET
|
|
</code>
|
|
|
|
<code>
|
|
>& TARGET
|
|
</code>
|
|
|
|
This special syntax redirects both, ''stdout'' and ''stderr'' to the specified target. It's **equivalent** to
|
|
<code>
|
|
> TARGET 2>&1
|
|
</code>
|
|
|
|
Since Bash4, there's ''&<nowiki>>>TARGET</nowiki>'', which is equivalent to ''<nowiki>>></nowiki> TARGET 2>&1''.
|
|
|
|
<wrap center important>This syntax is deprecated and should not be used. See the page about [[scripting:obsolete | obsolete and deprecated syntax]].</wrap>
|
|
|
|
|
|
===== Appending redirected output and error output =====
|
|
|
|
To append the cumulative redirection of ''stdout'' and ''stderr'' to a file you simply do
|
|
<code>
|
|
>> FILE 2>&1
|
|
</code>
|
|
|
|
<code>
|
|
&>> FILE
|
|
</code>
|
|
|
|
===== Transporting stdout and stderr through a pipe =====
|
|
<code>
|
|
COMMAND1 2>&1 | COMMAND2
|
|
</code>
|
|
|
|
<code>
|
|
COMMAND1 |& COMMAND2
|
|
</code>
|
|
|
|
|
|
===== Redirecting input =====
|
|
<code>
|
|
N < SOURCE
|
|
</code>
|
|
|
|
The input descriptor ''N'' uses ''SOURCE'' as its data source. If ''N'' is omitted, filedescriptor 0 (''stdin'') is assumed.
|
|
|
|
|
|
===== Here documents =====
|
|
<BOOKMARK:tag_heredoc>
|
|
|
|
<code>
|
|
<<TAG
|
|
...
|
|
TAG
|
|
</code>
|
|
|
|
<code>
|
|
<<-TAG
|
|
...
|
|
TAG
|
|
</code>
|
|
|
|
A here-document is an input redirection using source data specified directly at the command line (or in the script), no "external" source. The redirection-operator ''<nowiki><<</nowiki>'' is used together with a tag ''TAG'' that's used to mark the end of input later:
|
|
|
|
<code>
|
|
# display help
|
|
|
|
cat <<EOF
|
|
Sorry...
|
|
No help available yet for $PROGRAM.
|
|
Hehe...
|
|
EOF
|
|
</code>
|
|
|
|
As you see, substitutions are possible. To be precise, the following substitutions and expansions are performed in the here-document data:
|
|
* [[syntax:pe | Parameter expansion]]
|
|
* [[syntax:expansion:cmdsubst | Command substitution]]
|
|
* [[syntax:expansion:arith | Arithmetic expansion]]
|
|
|
|
You can avoid that by quoting the tag:
|
|
<code>
|
|
cat <<"EOF"
|
|
This won't be expanded: $PATH
|
|
EOF
|
|
</code>
|
|
|
|
Last but not least, if the redirection operator ''<nowiki><<</nowiki>'' is followed by a ''-'' (dash), all **leading TAB** from the document data will be ignored. This might be useful to have optical nice code also when using here-documents.
|
|
|
|
The tag you use **must** be the only word in the line, to be recognized as end-of-here-document marker.
|
|
|
|
<wrap center info>It seems that here-documents (tested on versions ''1.14.7'', ''2.05b'' and ''3.1.17'') are correctly terminated when there is an EOF before the end-of-here-document tag. The reason is unknown, but it seems to be done on purpose. Bash 4 introduced a warning message when end-of-file is seen before the tag is reached.</wrap>
|
|
|
|
|
|
|
|
===== Here strings =====
|
|
|
|
<code>
|
|
<<< WORD
|
|
</code>
|
|
|
|
The here-strings are a variation of the here-documents. The word ''WORD'' is taken for the input redirection:
|
|
|
|
<code>
|
|
cat <<< "Hello world... $NAME is here..."
|
|
</code>
|
|
|
|
Just beware to quote the ''WORD'' if it contains spaces. Otherwise the rest will be given as normal parameters.
|
|
|
|
The here-string will append a newline (''\n'') to the data.
|
|
|
|
===== Multiple redirections =====
|
|
|
|
More redirection operations can occur in a line of course. The order is **important**! They're evaluated from **left to right**.
|
|
If you want to redirect both, ''stderr'' and ''stdout'' to the same file (like ''/dev/null'', to hide it), this is **the wrong way**:
|
|
<code bash>
|
|
# { echo OUTPUT; echo ERRORS >&2; } is to simulate something that outputs to STDOUT and STDERR
|
|
# you can test with it
|
|
{ echo OUTPUT; echo ERRORS >&2; } 2>&1 1>/dev/null
|
|
</code>
|
|
Why? Relatively easy:
|
|
* initially, ''stdout'' points to your terminal (you read it)
|
|
* same applies to ''stderr'', it's connected to your terminal
|
|
* ''2>&1'' redirects ''stderr'' away from the terminal to the target for ''stdout'': **the terminal** (again...)
|
|
* ''1>/dev/null'' redirects ''stdout'' away from your terminal to the file ''/dev/null''
|
|
What remains? ''stdout'' goes to ''/dev/null'', ''stderr'' still (or better: "again") goes to the terminal. You have to swap the order to make it do what you want:
|
|
<code bash>
|
|
{ echo OUTPUT; echo ERRORS >&2; } 1>/dev/null 2>&1
|
|
</code>
|
|
|
|
===== Examples =====
|
|
|
|
How to make a program quiet (assuming all output goes to ''STDOUT'' and ''STDERR''?
|
|
<code>
|
|
command >/dev/null 2>&1
|
|
</code>
|
|
|
|
===== See also =====
|
|
* Internal: [[howto:redirection_tutorial | Illustrated Redirection Tutorial]]
|
|
* Internal: [[commands:builtin:set#tag_noclobber | The noclobber option]]
|
|
* Internal: [[commands:builtin:exec | The exec builtin command]]
|
|
* Internal: [[syntax:grammar:parser_exec | Simple commands parsing and execution]]
|
|
* Internal: [[syntax:expansion:proc_subst | Process substitution syntax]]
|
|
* Internal: [[scripting:obsolete | Obsolete and deprecated syntax]]
|