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.