Automating textual input from a bash script without using EOF

For nearly all programs, both echo $i | myprogram -options and myprogram -options <<<$i should work, by feeding the program $i through standard input.

<foo will use the contents of the file named foo as stdin.

<<foo will use the text between that and a line consisting solely of foo as standard input. This is a here document (heredoc), as Gilles said; EOF doesn't actually mean the end of the file, it's just a common heredoc delineator (we use "foo" instead in this example).

<<<foo will use the string "foo" as standard input. You can also specify a variable $foo, and the shell will use its contents as stdin, as I showed above. This is called a herestring, as it uses a short string in contrast to a whole block, as in a heredoc. Herestrings work in bash, but not in /bin/sh.


The syntax recommended by this website is called a here document. The input to the file program starts immediately below the line containing <<EOF, and it is not terminated by the end of the script, but by a line containing exactly the text EOF (take care not to have extra whitespace). By the way, you can use any end marker that doesn't contain any shell special character: EOF is not a keyword, it is merely traditional.

#!/bin/bash
for i in {1..100}
do
   myprogram -options <<EOF
$i
EOF
   for j in {1..42}; do
     myprogram2 <<EOF
$i
$j
EOF
   done
done

here documents as mentioned by both Kevin and Gilles above, or simple piping will work in many cases.

For more complicated situations, you may want to look into Expect or similar (e.g. the Expect::Simple CPAN module is a very easy to use perl implementation). personally, I prefer the perl module (Expect itself is tcl) but there are implementations for many common scripting languages. It's even possible to write a very primitive implementation of the idea in sh or bash using while and read.

The general idea of Expect and similar tools is to wait for a specified string or pattern in the output of a program, and then feed it whatever input you want.

A common example use is to automate login, by "expecting" (i.e. waiting for) the string "ogin:", send the login-name, then expect the string "word:" and send the password.

One final option, if you have the source of myprogram, is to just modify it to take the input you want to give it as a command line option. This might be a bit more work up-front, but will be a whole lot less aggravating than messing around with Expect or piping data into a program that wasn't designed to be used that way.

... and don't forget to submit your patch to myprogram back upstream :) Even if they don't like the way you've coded it, they might like the idea enough to add the feature themselves. Upstream devs tend to appreciate people who get off their butts and contribute rather than demand or complain.