views:

119

answers:

2

Consider something like:

cat file | command > file

Is this good practice? Could this overwrite the input file as the same time as we are reading it, or is it always read first in memory then piped to second command?

Obviously I can use temp files as intermediary step, but I'm just wondering..

t=$(mktemp)
cat file | command > ${t} && mv ${t} file
+13  A: 

No, it is not ok. All commands in a pipeline execute at the same time, and the shell prepares redirections before executing the commands. So, it is likely that the command will overwrite the file before cat reads it.

You need sponge(1) from moreutils.

Juliano
thanks, moreutils looks very useful! Does the same apply to redirection: `command < file > file` or even process substitution: `command <(cat file) > file` ?
Amro
Yes, it also applies in both cases. Keep in mind that the shell is free to setup the redirections in any order, so you should consider undefined behavior to access the same file twice in a single command or pipeline. Even it works occasionally, it is not guaranteed.
Juliano
+1  A: 

You can also use something like this (not recommended, use temp files in production code):

{ rm file && your_command > file; } < file
radoulov