I need to continually read from and write to a (virtual) file in bash, without closing the file in between. I'm looking for a program which will open the file for read and write, read from stdin and write what it reads to the file AND read from the file and write it to stdout. A bit like netcat
but for files.
The file in question is a virtual file in /sys (a custom thing in something I'm working on) to which one writes a command and reads to receive the response – where the write and subsequent read must be done in the same session, i.e. on the same file descriptor without closing it in between.
Easy to do in C – open("file", O_RDWR)
, write()
, read()
– note: no need to seek()
.
Is there a standard GNU tool or do I need to write one?
Best Answer
The redirection operator to open a file in read+write mode without truncation is
<>
in all Bourne-like shells (that maps toopen(file, O_RDWR|O_CREAT)
(thoughzsh
also throws in aO_NOCTTY
) orfopen(file, "w+")
):opens the
$file
on file descriptor 3 in read+write mode (without truncating it and creating it if it didn't exist).However, only
ksh93
andzsh
have seeking operators.dd
can seek, but not backwards. And note no shell exceptzsh
can have NUL bytes in their variables.In
zsh
:In
ksh93
:Portably, you could still open the file several times, for each offset you want, like here to read and write 2 bytes at offset 2 (provided they're not bytes with value 0 if not using
zsh
):Or:
To read and write to the same file,
ksh93
has two other interesting redirection operators:Would store the output of
tr
in a temporary file and iftr
is successful, rename that tofile
(beware the file is created anew, so with possibly different permissions and ownership).Same as the standard/Bourne
tr -d 0 < file 1<> file
except that iftr
succeeds,file
is truncated wheretr
finished writing. You can use that for filter commands that produce less output than they read input, or more precisely commands that would not read data that they've previously written.And
zsh
has the=(...)
form of process substitution which you can use as:(with similar effect and caveats as
ksh93
's>;
). Or:which would preserve attributes of
file
but means an extra copy.Now if you need to read and write at the same offset using the same file descriptor and neither zsh nor ksh93 are available, you could always revert to
perl
/python
/ruby
...Now, after re-reading the updated version of your question, it looks like your file is behaving more like a socket or bidirectional pipe, and not like a regular, seekable file.
In which case, it could be just a matter of:
or:
to feed data from and to that file as read from/to stdin/stdout.
Note that each
cat
reads/writes to its own copy of the file descriptor 3 open by the shell, but they share the same open file description so it should be equivalent.