Pass text to program expecting a file

Related to a question I asked on Stack Overflow: Passing multiple lines of code to wsadmin.sh?.

I have, as a string, a few lines of input that I need to feed into a command. The command, however, only accepts a file full of input.

Is there some way I could store the lines in a temporary file or pipe which never actually gets written to disk and then feed that directly into the program?

How do I go about acquiring the pipe, feeding the input into it, passing that pipe to the command, and then getting rid of the pipe?


Solution 1:

Another solution is to use Process Substitution in Bash. If your system has named pipes, you can use this feature.

It is used like this:

program_expecting_a_file <(list)

where list is a sequence of shell commands (actually pipelines; the full details are here). list will be executed, and its output will be connected to the pipe. The name of the pipe is then passed to your program.

NOTE: spaces are not allowed between < and (.

(The other substitution >(list) also works as you'd expect.)

In your specific case, you could use

program_expecting_a_file <(echo "$your_strings")

although you may find @meuh's solution to be more elegant.

Update: A great many usage examples are to be found over at the Advanced Bash Scripting Guide.

Solution 2:

You can use a bash here-doc. For example,

$ cat -n <<<'a
> b'
 1  a
 2  b

If you have something in a bash variable you can also interpolate it: eg <<<"path is $PATH".


If your command insists on a filename you can give it /dev/stdin. Eg:

$ sed -f /dev/stdin <<<'s/a/b/'

produces the output: s/b/b/.

Solution 3:

Depending on what is in the script, you may be able to use the special filename - (minus) which stands for stdin

$ mycmd -
Line 1
Line 2
^D

Another method which may work for you is to open the file /dev/fd/0 which again stands for stdin.

A third option may be to create a FIFO (First In First Out). That is like a file, but it has two ends to it - you write to one end and read from the other.

-- Process 1 --                  -- Process 2 --
$ mkfifo foo
$ cat foo
<waits>                          $ echo hello > foo
hello                            $
$ rm foo

Solution 4:

There's another option similar to the mycmd - solution, but even for programs which don't handle - specifically:

$ mycmd /dev/stdin
Line 1
Line 2
^D

/dev/stdin seems to be OS-related and it works for me on Debian GNU/Linux, but I'm not sure where else it will work, too.