I've created a really simple bash script that runs a few commands.
one of these commands needs user input during runtime. i.e it asks the user "do you want to blah blah blah?", I want to simply send an enter keypress to this so that the script will be completely automated.
I won't have to wait for the input or anything during runtime, its enough to just send the keypress and the input buffer will handle the rest.
echo -ne '\n' | <yourfinecommandhere>
or taking advantage of the implicit newline that echo generates (thanks Marcin)
echo | <yourfinecommandhere>
You can just use yes.
# yes "" | someCommand
You might find the yes command useful.
See man yes
Here is sample usage using expect:
#!/usr/bin/expect
set timeout 360
spawn my_command # Replace with your command.
expect "Do you want to continue?" { send "\r" }
Check: man expect for further information.
You could make use of expect (man expect comes with examples).
I know this is old but hopefully, someone will find this helpful.
If you have multiple user inputs that need to be handled you can use process substitution and use echo as a 'file' for cat with whatever is needed to handle the first input like this:
# cat ignores stdin if it has a file to look at
cat <(echo "selection here") | command
and then you can handle subsequent inputs by piping the yes command with the answer:
cat <(echo "selection here") | yes 'y' | command
Related
I saw the line data=$(cat) in a bash script (just declaring an empty variable) and am mystified as to what that could possibly do.
I read the man pages, but it doesn't have an example or explanation of this. Does this capture stdin or something? Any documentation on this?
EDIT: Specifically how the heck does doing data=$(cat) allow for it to run this hook script?
#!/bin/bash
# Runs all executable pre-commit-* hooks and exits after,
# if any of them was not successful.
#
# Based on
# http://osdir.com/ml/git/2009-01/msg00308.html
data=$(cat)
exitcodes=()
hookname=`basename $0`
# Run each hook, passing through STDIN and storing the exit code.
# We don't want to bail at the first failure, as the user might
# then bypass the hooks without knowing about additional issues.
for hook in $GIT_DIR/hooks/$hookname-*; do
test -x "$hook" || continue
echo "$data" | "$hook"
exitcodes+=($?)
done
https://github.com/henrik/dotfiles/blob/master/git_template/hooks/pre-commit
cat will catenate its input to its output.
In the context of the variable capture you posted, the effect is to assign the statement's (or containing script's) standard input to the variable.
The command substitution $(command) will return the command's output; the assignment will assign the substituted string to the variable; and in the absence of a file name argument, cat will read and print standard input.
The Git hook script you found this in captures the commit data from standard input so that it can be repeatedly piped to each hook script separately. You only get one copy of standard input, so if you need it multiple times, you need to capture it somehow. (I would use a temporary file, and quote all file name variables properly; but keeping the data in a variable is certainly okay, especially if you only expect fairly small amounts of input.)
Doing:
t#t:~# temp=$(cat)
hello how
are you?
t#t:~# echo $temp
hello how are you?
(A single Controld on the line by itself following "are you?" terminates the input.)
As manual says
cat - concatenate files and print on the standard output
Also
cat Copy standard input to standard output.
here, cat will concatenate your STDIN into a single string and assign it to variable temp.
Say your bash script script.sh is:
#!/bin/bash
data=$(cat)
Then, the following commands will store the string STR in the variable data:
echo STR | bash script.sh
bash script.sh < <(echo STR)
bash script.sh <<< STR
I have a shell-script main_script.sh, which will in term call 3 other scripts (a1.sh,a2.sh,a3.sh).
Now on execution of a1.sh/a2.sh/a3.sh I need to answer some verbose with Y/N.
I know that each of a1.sh/a2.sh/a3.sh will need 2 Y/N.
How can I implement main_script.sh,so I don't have to answer Y/N requests while execution?
It depends on how the scripts are written. You mentioned each script needing two Y. I presume that each Y will need to be followed by an enter key (newline). In this case, it could be as simple as using the following for main_script.sh:
#!/bin/bash
echo $'Y\nY\n' | bash a1.sh
echo $'Y\nY\n' | bash a2.sh
echo $'Y\nY\n' | bash a3.sh
Above, the echo command sends two Y and newline characters to each of the scripts. You can adjust this as needed.
Some scripts will insist that interactive input come from the terminal, not stdin. Such scripts are harder, but not impossible, to fool. For them, use expect/pexpect.
More details
Let's look in more detail at one of those commands:
echo $'Y\nY\n' | bash a1.sh
The | is the pipe symbol. It connects the standard out of the echo command to the standard input of the a1.sh command. If a1.sh is amenable, this may allow us to pre-answer any and all questions that a1.sh asks.
In this case, the output from the echo command is $'Y\nY\n'. This is a bash shell syntax meaning Y, followed by newline character, denoted by \n, followed by Y, followed by newline, \n. A newline character is the same thing that the enter or return key generates.
Using expect
If your script does not accept input on stdin, then expect can be used to automate the interaction with script. As an example:
#!/bin/sh
expect <<EOF1
spawn a1.sh
expect "?"
send "Y\r"
expect "?"
send "Y\r"
sleep 1
EOF1
expect <<EOF2
spawn a2.sh
expect "?"
send "Y\r"
expect "?"
send "Y\r"
sleep 1
EOF2
Is it possible to output text to a shell window, via bash script, that is user-editable? I essentially want to pre-fill certain information and give the user the ability to edit it if it's wrong.
For instance, if I were to write in a script:
echo -n "Enter your name: Anthony"
while read user_input
do
# do stuff with $user_input
done
How can I allow the user to inline edit the word Anthony only (aka, don't allow backspacing past the A in Anthony), and how can I store the value into a variable once the RETURN key is pressed?
EDIT
I'm looking for something similar to the -i option of read (see answer posted here), but this is only available on bash 4+. Is there an alternative for bash 3?
I needed similar setup recently so what I did was
$ cat a.sh
function input {
python -c '
import sys,readline
readline.set_startup_hook(lambda: readline.insert_text(sys.argv[2]))
sys.stderr.write(raw_input(sys.argv[1]))
' "$#" 3>&1 1>&2 2>&3
}
A=$( input 'question: ' default )
echo "A='$A'"
$ ./a.sh
question: default
A='default'
Well, it's not actually bash, but it made the job done.
I want to create a bash script that is simular to a programming interpreter like mongo, node, redis-cli, mysql, etc.
I want to be able to use a command like test and it behave like the examples above.
thomas#workstation:~$ test
>
How do I make a command that behaves like this? What is this called?
I want to be able to take the content and turn it into a variable.
thomas#workstation:~$ test
> hello world
hello world
thomas#workstation:~$
I only want to take one "entry" after enter is pressed once I want to be able to process the string "hello world" in the code, like echo it.
What is this called? How do I make one using BASH?
I think "read" is what you are looking for, isn't it?
here is a link with some examples: http://bash.cyberciti.biz/guide/Getting_User_Input_Via_Keyboard
so you can do stuff like this:
read -p "Enter your name : " name
echo "Hi, $name. Let us be friends!"
I'm sorry this doesn't answer you directly, but it might be worth it to look into using a more fully capable programming language such as Python, Ruby, or Perl for a task like this. In Python you can use the raw_input() function.
user_command = raw_input('> ')
would yield your prompt.
First, do not name your script test. That generates too much confusion. Whatever you call it, you can do many things:
#!/bin/sh
printf '> '
read line
echo "$line"
If your shell supports it:
#!/bin/sh
read -p '> ' line
echo "$line"
or
#!/bin/sh
printf '> '
sed 1q # This will print the input. To store in in a variable: a=$( sed 1q )
[spatel#tux ~]$ read a
Hello World!!!!!
[spatel#tux ~]$ echo $a
Hello World!!!!!
Key word that might be useful here is REPL (Read–eval–print loop) used primarily for programming languages or coding environments. Your browsers console is a great example of a REPL.
Node allows you use their REPL to build interactive apps.
If I run a bash script as
./myscript.sh zone=A build=release
Is there someway I can read the arguments based on the parameters instead of using $1, $2?
No. Unix shells are an ancient technology, hash maps were known at the time but not "en vogue." They needed more than 1 byte to implement so the professionals didn't want to use such a wasteful technology.
What else can you do? The usual solution is getopt(1).
An alternative is to write all options to a file and source that:
echo "$#" | tr ' ' '\n' > options
. ./options
echo "zone=${zone}"
Hope this is what you are asking for:
A="try"
try="something"
echo ${!A}
> something
This is close to what you want.
set -k
./myscript.sh zone=A build=release
will behave the same as
zone=A build=release ./myscript.sh
that is, myscript.sh will see zone and build with the given values in its environment.