I am learning bash and am not able to understand what is going wrong with the output redirection in the following example:
I have a file called myfile.txt with the following content.
Practice makes Perfect
I am going to use tr
command to replace P with p:
cat myfile.txt | tr P p
This does what I want, now I am going to put the result back into the original file:
cat myfile.txt | tr P p > myfile.txt
But after executing the above command myfile.txt is empty... why is this happening?
Update:
If I send the output to a different file, then it works as expected:
cat myfile.txt | tr P p > anotherfile.txt
Bash (and other POSIX-compliant shells) follow two rules that explain this behavior:
Redirection happens before commands run.
If a file exists, it is truncated (emptied) when redirection goes to the file as in
> myfile.txt
.So because there is
>
redirection the contents of themyinput.txt
get discarded andcat
prints nothing,cat
exits and closes the pipe andtr
closes the file without writing anything to it. Order in which commands start is not particularly important ( and it is not guaranteed, see Gille's answer here). But what is important is that redirection occurring before commands starting; that is each command's standard streams are prepared, and that's what causes empty file in the end.But it is possible to edit the same file tools like
sponge
, just not in this particular case.See also:
Use: sort -o instead of redirection. I n such a way you will be able to write to the same file.
In my opinion cat is not used in the correct intention. Normally cat is used to combine files, but often also misused to just use display simple files.
In your case I would use the tr command in the following way: