172

I have a bash script that employs the read command to read arguments to commands interactively, for example yes/no options. Is there a way to call this script in a non-interactive script passing default option values as arguments?

It's not just one option that I have to pass to the interactive script.

Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
sidharth sharma
  • 3,025
  • 6
  • 23
  • 20
  • 2
    If it is reading from stdin you could pipe in your input – lc. Jan 18 '13 at 04:46
  • 4
    As this question gets many duplicates, it is worth pointing out that it doesn't matter in which language the interactive program is written. It could be a C program which reads standard input, or an Erlang application, or whatever. There's something which runs from the command line and obnoxiously demands interactive input, and you'd like to automate it. – tripleee Mar 16 '17 at 04:37
  • Of course, if you have control over the obnoxious application, rewrite it so that it can read the answers noninteractively (through a configuration file, command-line options, or whatever). This is much more reliable and robust against changing the order or wording of interactive questions. – tripleee Jul 26 '18 at 13:29

5 Answers5

206

Many ways

pipe your input

echo "yes
no
maybe" | your_program

redirect from a file

your_program < answers.txt

use a here document (this can be very readable)

your_program << ANSWERS
yes
no
maybe
ANSWERS

use a here string

your_program <<< $'yes\nno\nmaybe\n'
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • 7
    It bears pointing out that this only works if the program reads standard input. Some programs go out of their way to read e.g. passwords interactively, even when standard input is a pipe. For passwords, this makes sense for security reasons; though some interactive programs are just simply poorly designed. – tripleee Mar 16 '17 at 05:02
  • @tripleee Along the lines of what you said, how does a script read passwords that is not affected by stdin? I know you can use `read` to grab stdin, what function can you use do what you described? – flow2k Oct 17 '17 at 19:03
  • In that case, you need to see if the program you're trying to interact with has a special way to send the input to it (e.g. sshpass, ssh-agent), or use expect to script the interaction. – glenn jackman Oct 17 '17 at 19:40
  • 2
    What programs like Expect do is run the client under a pseudo-tty where it looks to the client like there is a user with a terminal and a keyboard at the other end. You can't do that with a regular pipe. – tripleee Oct 18 '17 at 03:47
  • Important notice. This doesn't work if we add spaces to the supplied commands. – 71GA Jul 23 '18 at 13:48
  • @71GA, I don't understand your concern here. What problems have you encountered? – glenn jackman Jul 24 '18 at 14:47
  • What if there are multiple prompts one after the other? @glennjackman – ss301 Aug 09 '19 at 07:25
  • That's exactly what this answer addresses. Did you try it? – glenn jackman Aug 09 '19 at 10:29
  • How do you push enter after each parameter please? This is not working for me without enter: `echo "i 2 y y" | ~/Downloads/reaper_linux_x86_64/install-reaper.sh` – Richard Jul 20 '22 at 16:13
  • Ah, here we go, you need to add `-ne` to your script: `echo -ne "i \n 2 \n y \n y \n" | ~/Downloads/reaper_linux_x86_64/install-reaper.sh` – Richard Jul 20 '22 at 16:23
  • 1
    Or better, avoid `echo -e`; `printf '%s\n' i 2 y y | your_command`. Putting all the input on a single line obviously only passes in one line of input, i.e. answers the first prompt with all the text. – tripleee Mar 24 '23 at 10:42
64

For more complex tasks there is expect ( http://en.wikipedia.org/wiki/Expect ). It basically simulates a user, you can code a script how to react to specific program outputs and related stuff.

This also works in cases like ssh that prohibits piping passwords to it.

Dani Gehtdichnixan
  • 1,265
  • 1
  • 11
  • 21
20

You can put the data in a file and re-direct it like this:

$ cat file.sh
#!/bin/bash

read x
read y
echo $x
echo $y

Data for the script:

$ cat data.txt
2
3

Executing the script:

$ file.sh < data.txt
2
3
Guru
  • 16,456
  • 2
  • 33
  • 46
17

Just want to add one more way. Found it elsewhere, and is quite simple. Say I want to pass yes for all the prompts at command line for a command "execute_command", Then I would simply pipe yes to it.

yes | execute_command

This will use yes as the answer to all yes/no prompts.

  • 3
    This can also be customized to not just pass `y` but any string you like. For instance, to pass `n` it's enough to write `yes n | execute_command` – lupalby Jul 22 '22 at 07:47
10

You can also use printf to pipe the input to your script.

var=val
printf "yes\nno\nmaybe\n$var\n" | ./your_script.sh
spanchan
  • 181
  • 3
  • 6