17

Is there any way to create a virtual file, such that reading from the file actually reads from the stdout of a command; writing to the file is acually writing to the stdin of a command?

So far I have kludged this with an inotifywait on a file, which calls a command when the file is modified, taking it's input from the file and writing back to it.

I don't like that the inotifywait has to be constantly restarted though (and I have to ensure that it is always running). I only use this file perhaps twice a week.

17

You may be looking for a named pipe.

mkfifo f
{
  echo 'V cebqhpr bhgchg.'
  sleep 2
  echo 'Urer vf zber bhgchg.'
} >f
rot13 < f

Writing to the pipe doesn't start the listening program. If you want to process input in a loop, you need to keep a listening program running.

while true; do rot13 <f >decoded-output-$(date +%s.%N); done

Note that all data written to the pipe is merged, even if there are multiple processes writing. If multiple processes are reading, only one gets the data. So a pipe may not be suitable for concurrent situations.

A named socket can handle concurrent connections, but this is beyond the capabilities for basic shell scripts.

At the most complex end of the scale are custom filesystems, which lets you design and mount a filesystem where each open, write, etc., triggers a function in a program. The minimum investment is tens of lines of nontrivial coding, for example in Python. If you only want to execute commands when reading files, you can use scriptfs or fuseflt.

3

Some things to be aware of regarding named pipes: A pipe cannot - unlike a file - have multiple readers. Once its content is read it's gone. So you need to loop, i.e. you'll need to constantly push content into the pipe from the writer.

I've been searching for an answer myself to this question and the only other thing I've been able to come up with is scriptfs which is based on fuse.

1

What you describe is essentially a FIFO special file, see fifo(7). They are created by mkfifo(1), and a process can then open them under Linux for R/W (not all Unixy systems handle that). Two independent processes can then use it to communicate.

0

The easiest way to "Create a virtual file that is actually a command" is to extend the FUSE filesystem. It is very easy to do with libraries like fusepy.

Here is an example of an FUSE filesystem that lets you read HTTP/HTTPS/FTP files as if they were present on your own Linux box. You can similarly create something that runs any command for the same on read.

If you look at the source code it is hardly 50 lines of code (excluding any boilerplate code).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.