44

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?

3
  • 2
    Can you add an example of the command you're using, and how it's supposed to be invoked? Jul 13, 2015 at 7:27
  • 2
    Does that mean the program does not accept stdin?
    – Léo Lam
    Jul 13, 2015 at 11:47
  • I agree with both commenters above. It's impossible to suggest anything that may work without knowing the program's specs.
    – Larssend
    Jul 13, 2015 at 13:04

4 Answers 4

42

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.

5
  • The other two did not work in even the most trivial of cases. Yours passes the tests I've thrown at it so far. I have upvoted yours for now. I will come back and mark this as accepted if it does everything I need. Jul 13, 2015 at 14:29
  • Yours works perfectly. If you'd like, you can add it to the related question on StackOverflow and I can accept it over there, too. stackoverflow.com/questions/31374202/… Jul 13, 2015 at 15:22
  • Hi @ArtOfWarfare, glad to be of help. There is a comment over there already with the same proposed solution, so it wouldn't be right for me to post an answer there.
    – Edward
    Jul 14, 2015 at 8:50
  • You posted your solution before he did. Anyways, I've asked him to change his comment to an answer so I can accept it. If neither of you post answers within ~24 hours on that question, I'll just post the answer myself so I can accept it (I don't like leaving my questions as appearing unanswered once I've found what the answer is. It's just bad manners for future readers / potential answerers of the question.) Jul 14, 2015 at 12:07
  • Hi @ArtOfWarfare, I'm absolutely fine with what you propose!
    – Edward
    Jul 15, 2015 at 7:47
20

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/.

5
  • It's not clear from the question whether the command accepts input on stdin, and if not, this isn't going to work. I hope the OP clarifies.
    – David Z
    Jul 13, 2015 at 12:34
  • 1
    :( - This seemed super promising, but when I tried it, I got the error message "-f" option must be followed by a file name. Jul 13, 2015 at 14:19
  • A here-doc is for stdin. If your command absolutely needs -f and a filename, then provide the filename /dev/stdin. See my edit.
    – meuh
    Jul 13, 2015 at 14:46
  • I think after the edits it's absolutely a viable option!
    – Edward
    Jul 14, 2015 at 8:54
  • 1
    +1 for the /dev/stdin suggestion. The program I'm trying to call only accepts a filename, so I've combined /dev/stdin with a heredoc. Jan 15, 2019 at 14:41
7

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
4
  • 3
    It may be worth noting that the program has to be written to interpret - this way - it's not a feature of the shell or the operating system. Though of course most standard Linux utilities do follow this convention, as far as I know.
    – David Z
    Jul 13, 2015 at 12:32
  • 1
    Nope. This does not work for the program. There is an interactive mode, but I want to pass the commands to execute to this program from another program, and I don't want to get into rabbit-hole that is expect. Jul 13, 2015 at 14:16
  • @ArtOfWarfare I have just added a third option that may work.
    – Majenko
    Jul 13, 2015 at 15:06
  • Nice answer! The second & third options are basically like the <() solution, but more explicit - which may be very useful!
    – Edward
    Jul 14, 2015 at 8:53
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.

4
  • 1
    This seems like it might work, but what is ^D? Jul 13, 2015 at 17:04
  • ^D is a common notation for pressing Ctrl-D. ^D has the semantics of "end of input stream" here. It's probably more often seen in ^C or ^Z which stand for pressing Ctrl-C respectively for pressing Ctrl-Z. Jul 13, 2015 at 18:04
  • 1
    That does seem to work, but how would I programmatically put stuff into /dev/stdin and then close it? Jul 13, 2015 at 19:15
  • 1
    Just pipe something into that command and it should work, i.e. cat content | mycmd /dev/stdin. Just imagine different commands than cat here. Jul 13, 2015 at 19:29

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .