understanding shell redirection on non existant files
-
07-07-2019 - |
Question
ls > ls.out
this will include ls.out in the list too. My understanding is: > (shell output redirection operator is creating a file first (to take the STDOUT) if it is not already existing and then ls command is coming to play and it is including the just created ls.out file in the output. Is this correct? If not, can you please elaborate the workings of that command.
Similarly
wc temp > temp
Will print 0 0 0 temp inside the just created temp file.
This behavior of shell is interesting. I wonder, how it is actually working. BTW, both are exercises in The Unix Programming Environment Book. As I mentioned the answer above, I want some expert to correct my understanding.
Solution
When redirecting standard output with >
, the shell will create the file (as an empty file) if it doesn't already exist. Further, that file is opened before the shell forks and execs the command being executed. When you do wc temp > temp
, the shell opens the file for writing and then forks and execs wc
, passing on its open file handles in the process.
OTHER TIPS
Oversimplification:
ls
is looking at the inode (directory entry) which the redirection created.
wc
can see the inode that the redirection created, but when it looks at the contents they are empty because it (wc
) hasn't written them yet.
Edit:
First, in both cases, the redirection (>ls.out
or >temp
) creates an empty file. An entry (inode) in the directory is made to point to the location of the file and contain some information about it. See the Wikipedia article on inodes.
Next, in the case of ls
, all the entries in the directory, including the one for ls.out
which was just created, are read and written to stdout
(which in this case becomes the contents of ls.out
).
Or, in the case of wc
, it's counting the newline, word and byte counts of the recently created file called temp
which is empty so it writes the zero counts into the file after it counts (nothing).
The contents of the files (temp
or ls.out
) are not written until after all the reading is done so they can't have been included.
For a better way to compare what ls
and wc
are doing, try this command (when ls.out
is non-existent):
ls -l > ls.out
You should see that the file size for ls.out
is zero according to the list contained inside (cat ls.out
), but if you do ls -l ls.out
you'll see that it's not zero. This corresponds to what you see happening with wc
.
consider wc -l temp > temp
If temp
already existed and had say 20 lines still the result of cat temp
after executing the above command, it will be 0 temp.
I think this is because the shell creates a new empty temp
even if temp
existed thus overwriting the existing temp and hence when wc
tries to count the num of lines in temp
it gets zero.
In effect > temp
is executed by shell first and then wc -l temp
is executed.