I/O redirection in scripts
I/O redirection is a shell feature. It is triggered by shell operators like < , > , and | . What is triggered? Some portion of the shell's source code, originally written in C, to do the job. This code needs to shuffle the device associations of the file descriptor integers in the descriptor table. It does that by using appropriate system function calls, notably creat( ) and dup( ).
How can a shell script do that? Well, those operators can appear in the script. But then, as above, the code that ultimately does the descriptor manipulation is that of the shell, in the shell. The descriptors get shuffled, but that's all implicit. What is explicit, in the script, is merely the operator. That's sort of cheating.
Can't a script manipulate file descriptors explicitly? Yes; the shell "exec" builtin and specialized redirection operators can be used. While the exec builtin's mainstream use is as front-end to the exec system function call, it has a secondary use. Used mainstream, you give it a command name and it causes a code overwrite within a process, by calling the system function. But we are interested in the special secondary case; that's when we give it no command. While you can't not give a command (i.e., filename argument) to it's namesake system function, you can omit it with the builtin. In that case, it doesn't call the system function at all but becomes a file descriptor manipulator instead of a code overwriter. It's still called exec, but it doesn't really "do exec" in this case. Here is the relevant portion of the bash man page:
exec [-cl] [-a name] [command [arguments]] If command is specified, it replaces the shell. ...If command is not specified, any redirections take effect in the current shell, and the return status is 0. If there is a redirection error, the return status is 1.
Also, the entire excerpt from the bash man page about redirection is reproduced for reference at the bottom of this page.
In particular, you might be able to use:
exec n>&m
exec n<&m
exec > filename
exec < filename
n>&-
n<&-
where n and m are file descriptor integers ( 0-9 ).
The exercise to perform:
Write a script named "redirection" that will operate on a file named in.txt. Create a file by that name containing any text of mixed case. Your script will output in.txt's content translated to upper case into a file named out.txt.
Do this by mapping file descriptors. You would normally meet the specification on the command line by:
cat < in.txt | tr a-z A-Z > out.txt
In your script, similarly use a pipe from cat to tr. However, do not refer to either file in your pipeline. Omit the indirect of cat's input. Omit the redirect of tr's output. Let cat pull its input and tr push its output using their default places for doing so. But before executing the pipeline, remap those places so that when cat goes to its default place it finds in.txt, and when tr goes to its default place it finds out.txt. When finished, restore any file descriptors you altered to their original state and print out an advisory message that the task succeeded. Here is suggested pseudocode:
redirect standard input to some unused "utility" file descriptor
(to restore from later)
redirect standard output to some other unused file descriptor (same purpose)
redirect the script's input from the input file
redirect its output to the output file
pipe from cat to tr for uppercase translation ( no filenames )
restore standard input and standard output, using the respective utility
descriptors you equated to them before you changed them
close both utility descriptors
print success message
When finished leave your "redirection" script in your assignments
subdirectory.
From bash man page:
REDIRECTION
Before a command is executed, its input and output may be redirected
using a special notation interpreted by the shell. Redirection may
also be used to open and close files for the current shell execution
environment. The following redirection operators may precede or appear
anywhere within a simple command or may follow a command. Redirections
are processed in the order they appear, from left to right.
In the following descriptions, if the file descriptor number is omit-
ted, and the first character of the redirection operator is <, the
redirection refers to the standard input (file descriptor 0). If the
first character of the redirection operator is >, the redirection
refers to the standard output (file descriptor 1).
The word following the redirection operator in the following descrip-
tions, unless otherwise noted, is subjected to brace expansion, tilde
expansion, parameter expansion, command substitution, arithmetic expan-
sion, quote removal, pathname expansion, and word splitting. If it
expands to more than one word, bash reports an error.
Note that the order of redirections is significant. For example, the
command
ls > dirlist 2>&1
directs both standard output and standard error to the file dirlist,
while the command
ls 2>&1 > dirlist
directs only the standard output to file dirlist, because the standard
error was duplicated as standard output before the standard output was
redirected to dirlist.
Bash handles several filenames specially when they are used in redirec-
tions, as described in the following table:
/dev/fd/fd
If fd is a valid integer, file descriptor fd is dupli-
cated.
/dev/stdin
File descriptor 0 is duplicated.
/dev/stdout
File descriptor 1 is duplicated.
/dev/stderr
File descriptor 2 is duplicated.
/dev/tcp/host/port
If host is a valid hostname or Internet address, and port
is an integer port number or service name, bash attempts
to open a TCP connection to the corresponding socket.
/dev/udp/host/port
If host is a valid hostname or Internet address, and port
is an integer port number or service name, bash attempts
to open a UDP connection to the corresponding socket.
A failure to open or create a file causes the redirection to fail.
Redirections using file descriptors greater than 9 should be used with
care, as they may conflict with file descriptors the shell uses inter-
nally.
Redirecting Input
Redirection of input causes the file whose name results from the expan-
sion of word to be opened for reading on file descriptor n, or the
standard input (file descriptor 0) if n is not specified.
The general format for redirecting input is:
[n]<word
Redirecting Output
Redirection of output causes the file whose name results from the
expansion of word to be opened for writing on file descriptor n, or the
standard output (file descriptor 1) if n is not specified. If the file
does not exist it is created; if it does exist it is truncated to zero
size.
The general format for redirecting output is:
[n]>word
If the redirection operator is >, and the noclobber option to the set
builtin has been enabled, the redirection will fail if the file whose
name results from the expansion of word exists and is a regular file.
If the redirection operator is >|, or the redirection operator is > and
the noclobber option to the set builtin command is not enabled, the
redirection is attempted even if the file named by word exists.
Appending Redirected Output
Redirection of output in this fashion causes the file whose name
results from the expansion of word to be opened for appending on file
descriptor n, or the standard output (file descriptor 1) if n is not
specified. If the file does not exist it is created.
The general format for appending output is:
[n]>>word
Redirecting Standard Output and Standard Error
Bash allows both the standard output (file descriptor 1) and the stan-
dard error output (file descriptor 2) to be redirected to the file
whose name is the expansion of word with this construct.
There are two formats for redirecting standard output and standard
error:
&>word
and
>&word
Of the two forms, the first is preferred. This is semantically equiva-
lent to
>word 2>&1
Here Documents
This type of redirection instructs the shell to read input from the
current source until a line containing only word (with no trailing
blanks) is seen. All of the lines read up to that point are then used
as the standard input for a command.
The format of here-documents is:
<<[-]word
here-document
delimiter
No parameter expansion, command substitution, arithmetic expansion, or
pathname expansion is performed on word. If any characters in word are
quoted, the delimiter is the result of quote removal on word, and the
lines in the here-document are not expanded. If word is unquoted, all
lines of the here-document are subjected to parameter expansion, com-
mand substitution, and arithmetic expansion. In the latter case, the
character sequence \<newline> is ignored, and \ must be used to quote
the characters \, $, and ‘.
If the redirection operator is <<-, then all leading tab characters are
stripped from input lines and the line containing delimiter. This
allows here-documents within shell scripts to be indented in a natural
fashion.
Here Strings
A variant of here documents, the format is:
<<<word
The word is expanded and supplied to the command on its standard input.
Duplicating File Descriptors
The redirection operator
[n]<&word
is used to duplicate input file descriptors. If word expands to one or
more digits, the file descriptor denoted by n is made to be a copy of
that file descriptor. If the digits in word do not specify a file
descriptor open for input, a redirection error occurs. If word evalu-
ates to -, file descriptor n is closed. If n is not specified, the
standard input (file descriptor 0) is used.
The operator
[n]>&word
is used similarly to duplicate output file descriptors. If n is not
specified, the standard output (file descriptor 1) is used. If the
digits in word do not specify a file descriptor open for output, a
redirection error occurs. As a special case, if n is omitted, and word
does not expand to one or more digits, the standard output and standard
error are redirected as described previously.
Moving File Descriptors
The redirection operator
[n]<&digit-
moves the file descriptor digit to file descriptor n, or the standard
input (file descriptor 0) if n is not specified. digit is closed after
being duplicated to n.
Similarly, the redirection operator
[n]>&digit-
moves the file descriptor digit to file descriptor n, or the standard
output (file descriptor 1) if n is not specified.
Opening File Descriptors for Reading and Writing
The redirection operator
[n]<>word
causes the file whose name is the expansion of word to be opened for
both reading and writing on file descriptor n, or on file descriptor 0
if n is not specified. If the file does not exist, it is created.