Reputation: 177
I am trying to execute the following command on UNIX.
$ cat file1>file2>file3
In the scenario where only the file1
is present, what I think should happen is:
file2
should be created with the content of file1
,file3
from content of file2
.What actually happening is that:
file2
and file3
get created andfile3
has the content of file1
file2
does not — file2
is created but it is blank/empty.Can anyone explain why this happens?
Upvotes: 3
Views: 7352
Reputation: 754110
Others have explained why file2
is empty (but, succinctly, it is because the redirection to file3
replaces the redirection to file2
, so file2
is created or emptied but file3
gets the data from file1
).
If you want the output in two files, use tee
:
cat file1 | tee file2 > file3
There are other ways to do that, including:
tee < file1 file2 > file3
which has a certain pleasing symmetry to it. It also avoid the UUoC (Useless Use of cat
) tag which the other is open to. However, if you had a variable number of input files (0 or standard input, or many – meaning more than one — or you needed to process command line arguments), then cat
would still be correct. Note that tee
can generate multiple files (so in some circumstances cat "$@" | tee file1 file2 file3 >/dev/null
might make sense).
Upvotes: 4
Reputation: 10563
What's happening there is about how the standard input/output are managed.
You have cat file1>file2>file3
and what it is doing here is almost the same as
cat file1 > file3
Because file2 has it input redirected to the output
So, even if your file2 has some text in it and you execute
cat file1 > file2 > file3
The content of file3 will still be the content of file1, why ?
CAT(1) User Commands CAT(1)
NAME cat - concatenate files and print on the standard output
DESCRIPTION Concatenate FILE(s), or standard input, to standard output.
Check the or (or standard input to standard output). You're redirecting the standard input from file2 directly to the standard output.
Let's supose this scenario:
If you do cat file1 > file2 > file3
then the contents of the files will be
file2 send to the output what file1 send to the input
Upvotes: 1
Reputation: 126253
The shell interprets file redirections from left to right before running the command. So when you enter
cat file1 > file2 > file3
it first does the redirection > file2
-- creating or emptying file2
and pointing stdout at it. Then it does > file 3
, creating or emptying file3
and pointing stdout there. Finally it runs the command cat file1
, which reads file1
and copies it to stdout. Since stdout is (now) pointing at file3
, file3
ends up being a copy of that. Since nothing was written to stdout when it pointed at file2
, file2
ends up empty.
Upvotes: 6
Reputation: 932
strace
gives the answer.
open("file2", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
dup2(3, 1) = 1
close(3) = 0
open("file3", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
dup2(3, 1) = 1
close(3) = 0
execve("/bin/cat", ["cat", "file1"], [/* 38 vars */]) = 0
The second dup2() closes the file descriptor associated with file2. When cat runs, its stdout is file3.
Upvotes: 3