tee newOutputFile < existingInputFile > newOutputFile2
How exactly will tee
take in the arguments? Would it be like this?
- Tee will first process
newOutputFile < existingInputFile
So the contents of existingInputFile will be written into newOutputFile newOutputFile > newOutputFile2
So the contents of newOutputFile will be written into newOutputFile 2
I am trying to write a shell that process this particular command. However, I am confused as to which order to pass in the arguments to tee
. The way I have coded my program up it will do
tee newOutputFile2 < existingInputFIle
The
tee
command is a regular Unix program, just likesh
orsort
orcat
.All the I/O redirection work involved in handling
< existingInputFile
and> newOutputFile2
is done by the shell before thetee
command is invoked (after thefork
that creates the process that will execute thetee
command). The command is invoked with its standard input coming fromexistingInputFile
and with its standard output going tonewOutputFile2
. The only arguments given totee
areargv[0]
(the stringtee
) andargv[1]
(the stringnewOutputFile
), plus a null pointer to mark the end of the argument list.Note specifically that the shell is not involved in the actual reading of
existingInputFile
; it just opens it for reading and connects it to the standard input oftee
, but has no knowledge of whether thetee
command actually reads it or not. Similarly, the shell is not involved in the actual writing tonewOutputFile2
; it just opens and truncates it (or creates it) and connects it to the standard output oftee
, but has no knowledge of whether thetee
command actually writes anything to it. In this context, while thetee
command is running, the parent shell is completely passive, doing no I/O.By design,
tee
reads its standard input and write one copy of everything to each of the files given in its argument list and one more copy to standard output.The shell is only involved in opening and closing, but not in the reading and writing, of the files. In your command line
tee newOutputFile < existingInputFile > newOutputFile2
, the command istee
and the only other argument isnewOutputFile
. In general, the command (tee
in this case) has no knowledge of the name of the file that is providing it with standard input, nor of the name of the file that it is writing to on its standard output. Indeed, especially withtee
, the input is most often a pipe rather than a file, and very often the output is also a pipe rather than a file:In your own shell program, you could use
dup2()
to duplicate the file descriptor you'd opened separately so that it becomes standard input:Note that it is important to close
fd
in this scenario. Otherwise, the command is run with at least one extra file descriptor open that was not specified in the command line. You'd have a similar block of code for the standard output redirection.Or you could use:
This is because
open()
returns the lowest available previously not open file descriptor, so by closing 0, you know thatopen()
will return 0 on success and -1 on failure (even if 0 was previously closed). Then, by induction, you know that after closing 1,open()
will return 1 on success and -1 on failure (even if 1 was previously closed). You don't normally tinker with standard error unless the command line includes I/O redirection such as2>/dev/null
or2>&1
or something similar.If you prefer, you can write 0644 as:
(and add
|O_IWGRP|O_IWOTH
if you want to go with group and other write permission (0666); the permissions will be modified by theumask
anyway). Personally, I find the octal a lot easier to read, but I started using octal permissions a number of years before theO_Ixyyy
names were invented.