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?cat
or<
will make no difference./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
.