I have a bash script, a.sh
And when I run a.sh, I need to fill several read. Let's say it like this
./a.sh
Please input a comment for script usage
test (I need to type this line mannually when running the script a.sh, and type "enter" to continue)
Now I call a.sh in my new script b.sh. Can I let b.sh to fill in the "test" string automaticlly ?
And one other question, a.sh owns lots of prints to the console, can I mute the prints from a.sh by doing something in my b.sh without changing a.sh ?
Thanks.
Within broad limits, you can have one script supply the standard input to another script.
However, you'd probably still see the prompts, even though you'd not see anything that satisfies those prompts. That would look bad. Also, depending on what a.sh does, you might need it to read more information from standard input — but you'd have to ensure the script calling it supplies the right information.
Generally, though, you try to avoid this. Scripts that prompt for input are bad for automation. It is better to supply the inputs via command line arguments. That makes it easy for your second script, b.sh, to drive a.sh.
a.sh
#!/bin/bash
read myvar
echo "you typed ${myvar}"
b.sh
#!/bin/bash
echo "hello world"
You can do this in 2 methods:
$ ./b.sh | ./a.sh
you typed hello world
$ ./a.sh <<< `./b.sh`
you typed hello world
Related
To illustrate my issue and questions consider two scripts.
Script1.sh
#!/bin/sh
test=1
echo $test
Script2.sh
#!/bin/sh
$(Script1.sh)
When I run Script1.sh from the command line directly via ./Script1.sh it produces the desired output.
1
However when I run Script2.sh which calls Script1.sh, instead I get the following error message:
Script2.sh: line 1: 1: command not found
It thinks that the integer 1 is a command for some odd reason?
I found a cheap work around which is to set a variable from the first script and pass it to the second script as a parameter but I would like to understand why this is failing.
Also, when I changed my variables value from 1 to "some text", I would expect that my echo would print "some text" to the screen. But when I call Script2.sh (which ultimately just calls Script1.sh) it doesn't print the echo to the screen. Why is that, and how do I resolve it so I can see the echo output the same as if I would have called Script1.sh directly?
Any advice would be greatly appreciated.
You're calling it wrong by using command substitution. Just use source or a subshell if you want it:
. ./Script1.sh
( ./Script1.sh )
The second one is a bit redundant since it will always run in another shell anyway, so this would make more sense instead:
( . ./Script1.sh )
I have a script that calls an application that requires user input, e.g. run app that requires user to type in 'Y' or 'N'.
How can I get the shell script not to ask the user for the input but rather use the value from a predefined variable in the script?
In my case there will be two questions that require input.
You can pipe in whatever text you'd like on stdin and it will be just the same as having the user type it themselves. For example to simulating typing "Y" just use:
echo "Y" | myapp
or using a shell variable:
echo $ANSWER | myapp
There is also a unix command called "yes" that outputs a continuous stream of "y" for apps that ask lots of questions that you just want to answer in the affirmative.
If the app reads from stdin (as opposed to from /dev/tty, as e.g. the passwd program does), then multiline input is the perfect candidate for a here-document.
#!/bin/sh
the_app [app options here] <<EOF
Yes
No
Maybe
Do it with $SHELL
Quit
EOF
As you can see, here-documents even allow parameter substitution. If you don't want this, use <<'EOF'.
the expect command for more complicated situations, you system should have it. Haven't used it much myself, but I suspect its what you're looking for.
$ man expect
http://oreilly.com/catalog/expect/chapter/ch03.html
I prefer this way: If You want multiple inputs... you put in multiple echo statements as so:
{ echo Y; Y; } | sh install.sh >> install.out
In the example above... I am feeding two inputs into the install.sh script. Then... at the end, I am piping the script output to a log file to be archived and viewed for later.
I tried this technique for storing the output of a command in a BASH variable. It works with "ls -l", but it doesn't work when I run an apple script. For example, below is my BASH script calling an apple script.
I tried this:
OUTPUT="$(osascript myAppleScript.scpt)"
echo "Error is ${OUTPUT}"
I can see my apple script running on the command line, and I can see the error outputting on the command line, but when it prints "Error is " it's printing a blank as if the apple script output isn't getting stored.
Note: My apple script is erroring out on purpose to test this. I'm trying to handle errors correctly by collecting the apple scripts output
Try this to redirect stderr to stdout:
OUTPUT="$(osascript myAppleScript.scpt 2>&1)"
echo "$OUTPUT"
On success, the script's output is written to STDOUT. On failure, the error message is written to STDERR, and a non-zero return code set. You want to check the return code first, e.g. if [ $? -ne 0 ]; then..., and if you need the details then you'll need to capture osascript's STDERR.
Or, depending what you're doing, it may just be simplest to put set -e at the top of your shell script so that it terminates as soon as any error occurs anywhere in it.
Frankly, bash and its ilk really are a POS. The only half-decent *nix shell I've ever seen is fish, but it isn't standard on anything (natch). For complex scripting, you'd probably be better using Perl/Python/Ruby instead.
You can also use the clipboard as a data bridge. For example, if you wanted to get the stdout into the clipboard you could use:
osascript myAppleScript.scpt | pbcopy
In fact, you can copy to clipboard directly from your applescript eg. with:
set the clipboard to "precious data"
-- or to set the clipboard from a variable
set the clipboard to myPreciousVar
To get the data inside a bash script you can read the clipboard to a variable with:
data="$(pbpaste)"
See also man pbpase.
I am writing a script to become a user (let's call it genomics) via the cmd "sudo /etc/bgenomics" (this is setup by our admin) and run some bash code as that user, namely run a cmd, catch the exit code and take the appropriate action.
The problem is the bash code inside the here doc get printed to the screen, which is distracting and looks really unelegant.
Here's an illustration:
#!/bin/bash
name='George'
sudo /etc/bgenomics <<Q
/bin/bash
if (( 2 == 2 )); then
echo "my name is $name"
grep zzz /etc # will return nothing and $? = 1
echo \$? # this should be 1 after the above cmd
fi
Q
The if statement is just there to show how annoying it is when printed.
Right now all of the following is printed to the screen:
Script started, file is /var/tmp/genomicstraces/c060644.20140617143003.11536
Script done, file is /var/tmp/genomicstraces/c060644.20140617143003.11536
brainiac-login-02$brainiac-login-02$/bin/bash
bash-3.2$ if (( 2 == 2 )); then
> echo "my name is George"
> grep zzz /etc # will return nothing and 0 = 1
> echo $? # this should be 1 after the above cmd
> fi
my name is George
1
The only parts I want to see are "my name is George" and "1". Can it be done?
Is another process calling this script? Output shouldn't normally appear unless bash is called with '-x'. Try modifying the first line of your script if you cannot disable echo in the calling process:
#!/bin/bash +x
You may also want to remove the call to /bin/bash after the sudo command unless you really wish to start another shell within your shell.
The here document supplies input to the bgenomics script via its standard input. What happens to that input is up to that script.
If you want the script to print some of its input, and not print some of its input, you have to modify the script.
If bgenomics is actually a wrapper for an interactive shell session (as it seems to be, judging by the Script started and Script done traces), then here documents are not the best way to feed input into it.
A good way is to use the expect utility, which controls interactive programs via a pseudo-terminal device and provides a scripting language with a great deal of control. expect can suppress all unwanted input from an interactive program. It can look for specific outputs from the program, and supply responses. For instance it can look for a login: string coming from the interactive session, and send a user name.
The program bgenomics has an invocation of script in it to record what the script did. Talk to the person in charge of that to understand what their intentions are. Until you understand the purpose of bgenomics you risk screwing up what the author of that is trying to do.
$ script /tmp/junk.txt
Script started, file is /tmp/junk.txt
$ date # this is a child shell of the script command
Tue Jun 17 21:04:14 EDT 2014
$ exit
Script done, file is /tmp/junk.txt
I'm making a shell script and I want to know if it's possible to write directly to the command line when the script is executed ?
Example :
user#localhost:/home/user$./script.sh
... output
... another output
... another output
... last output
user#localhost:/home/user$I want to write here on the command line
I don't want to "echo" some text, I want to write directly at the prompt.
Thanks!
No, you can't do that. If you want user to invoke your provided command after your script is finished - why not just prompt user for confirmation?
If you just want the text to show up there, but not be able to do anything with it, you can do this.
File test.sh:
echo "Output"
./test2.sh &
File test2.sh:
echo "Output2"
Notice how the first script calls the second script with the & at the end.
In this case, "Output2" will be written to the prompt, but it can't be deleted and will have no effect on the next command at all. But if this is something you're doing to grab the user's attention, it would work.
In ksh:
print -s $(script)
will print to the command history. Wrap this in a function and you'll have something close to what you are asking for.
If you are using X environment install xclip and xdotool, then:
#!/bin/bash
your scripts....
echo -n your command to write 2>&1|xclip
xdotool click 2