Passing arguments to an interactive program non-interactively
Asked Answered
C

5

180

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.

Crisper answered 18/1, 2013 at 4:45 Comment(3)
If it is reading from stdin you could pipe in your inputFalse
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.Whiffen
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.Whiffen
C
66

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.

Chufa answered 18/1, 2013 at 10:56 Comment(1)
... Though the proper solution in the SSH case is to switch to public-key authentication.Whiffen
H
213

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'
Hatti answered 18/1, 2013 at 10:34 Comment(11)
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.Whiffen
@Whiffen 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?Oui
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.Hatti
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.Whiffen
Important notice. This doesn't work if we add spaces to the supplied commands.Morbid
@71GA, I don't understand your concern here. What problems have you encountered?Hatti
What if there are multiple prompts one after the other? @glennjackmanMiguelinamiguelita
That's exactly what this answer addresses. Did you try it?Hatti
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.shVictor
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.shVictor
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.Whiffen
C
66

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.

Chufa answered 18/1, 2013 at 10:56 Comment(1)
... Though the proper solution in the SSH case is to switch to public-key authentication.Whiffen
B
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
Bats answered 18/1, 2013 at 4:48 Comment(1)
thats the answer also telling how to handle the inputs coming from any source, perfectEconomical
S
18

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.

Starlastarlene answered 24/5, 2016 at 4:44 Comment(1)
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_commandDustcloth
S
11

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

var=val
printf "yes\nno\nmaybe\n$var\n" | ./your_script.sh
Sapotaceous answered 10/6, 2020 at 1:21 Comment(2)
That's what saved me. Thank you @spanchan.Illnatured
I don't understand why, but using printf works for certain programs (such as wml), when none of the other techniques did.Koonce

© 2022 - 2024 — McMap. All rights reserved.