I thought I had a good handle on bash file redirection, and generally I try to avoid "useless use of cat", but I experienced some unexpected behaviour with a script and I would like to understand why it occurs.
Within a bash script, I execute:
somecommand < file1 > file2
My expectation was that file1 is safe and opened in a read-only manner. In practice, I found that file1 can be overwritten. How/why does this happen, and is there a way to prevent it without resorting to a cat
?
If it's working how I imagine (the process ends up with a direct rw file descriptor?), it seems like it should be considered dangerous to redirect files this way, yet I've never seen this behaviour mentioned before.
To add some specifics from my case: the command in question is sops, which in the background is doing some GPG stuff. The GPG password prompt is sometimes† being written to the file used for input, overwriting it. The complete command I used is:
sops --input-type json --output-type json -d /dev/stdin < ./secrets/file.json > ./secrets/file-decrypted.json
I have since switched to cat file1 | sops.. > file2
and everything works as expected. I would have said this was a "useless use of cat" - but it doesn't seem so useless anymore!
†It seems to be when gpg-agent is not running and prompts for the first time.
file1
can still be overwritten just like before. You said it only happens "sometimes", so maybe it just hasn't happened yet with your cat version? – terdon Oct 05 '20 at 15:23cat
or<
will make no difference. – terdon Oct 05 '20 at 15:31/dev/stdin
. The lack of/dev/stdin
in the first code block can be confusing, as you would be safe with only the< file
redirection (again, if I understood it correctly). – Quasímodo Oct 05 '20 at 16:39/dev/stdin
argument is very relevant. But a UUoC does not always help: this will go into a infinite loop:echo text | tee /dev/fd/0
. Can you guess why? As to the idea that redirections let a program receive "a copy of the data", I don't see how someone would happen upon it other than by reading bad stackexchange answers or other such "tended garden"/hivemind products ;-) – Oct 06 '20 at 02:29/dev/stdin
, it still happens because that script/program is opening/dev/stdin
explicitly at some point (or one of its "aliases":/dev/fd/0
,/proc/self/fd/0
,/proc/<pid>/fd/0
, etc). A process is not able to write to file descriptor open in read-only mode, as fd 0 is incmd < file
. – Oct 06 '20 at 08:30cat
. – Reid Oct 06 '20 at 20:35