A simple if/else bash script which reacts to user's yes/no input? [duplicate] - bash

This question already has answers here:
How do I prompt for Yes/No/Cancel input in a Linux shell script?
(37 answers)
Closed 7 years ago.
I basically have a bash script which executes 5 commands in a row. I want to add a logic which asks me "Do you want to execute command A" and if I say YES, the command is executed, else the script jumps to another line and I see the prompt "Do you want to execute command B".
The script is very simple and looks like this
echo "Running A"
commandA &
sleep 2s;
echo "done!"
echo "Running B"
commandB &
sleep 2s;
echo "done!"
...

Use the read builtin to get input from the user.
read -p "Run command $foo? [yn]" answer
if [[ $answer = y ]] ; then
# run the command
fi
Put the above into a function that takes the command (and possibly the prompt) as an argument if you're going to do that multiple times.

You want the Bash read builtin. You can perform this in a loop using the implicit REPLY variable like so:
for cmd in "echo A" "echo B"; do
read -p "Run command $cmd? "
if [[ ${REPLY,,} =~ ^y ]]; then
eval "$cmd"
echo "Done!"
fi
done
This will loop through all your commands, prompt the user for each one, and then execute the command only if the first letter of the user's response is a Y or y character. Hope that helps!

Related

Can a bash script distinguish between being called as a script and being run as a "source"? [duplicate]

This question already has answers here:
How to detect if a script is being sourced
(22 answers)
Closed 3 years ago.
I have a bash script that has inside it:
exit 1
When I "source" this script instead of running it, it causes the caller to exit.
Is there a way that the script can determine that it's being run with "source" and not as its script?
You can use this check inside your script:
[[ $0 = $BASH_SOURCE ]] && echo "normal run" || echo "sourced run"
Or using if/else/fi wherever you're calling exit:
if [[ $0 = $BASH_SOURCE ]]; then
exit 1
else
# don't call exit
echo "some error..."
fi

Run a command in bash and keep it running until the user choose the no option

How do I make this work? I'm really trying to learn on my own.
But I'm really not getting this. I want to run a command in the
background and prompt a user whether they would like it to keep running
or not. If not, kill the command. I know I'm missing something. I'm just
not sure what.
Here's my code:
command > /dev/null 2>&1 &
echo
until [[ $REPLY =~ ^[Yy]$ ]] ;
do
echo
read -p "Would you like to stop the command [Yy/Nn]? " -n 1 -r
# Stop stop the command
killall -9 command
done
It is a little unclear what you want your loop frequency to be, but presuming you just want to block until the user types Yy, you can simply start command in the background, save its process ID (e.g. PID) using the bash special variable $!. Then simply loop until you get a Yy (which in bash, you can simply use the parameter expansion ${var,,} to evaluate var in lower-case). Upon received a Yy answer (using ans as the variable to store the response), you could do something similar to:
#!/bin/bash
command & >/dev/null 2>&1 # start command in background
cmdpid=$! # save the PID of command
ans=
while :; do # infinite loop until y or Y
printf "\nWould you like to stop the command (y/n)? "
read -n 1 -r ans # read ans
[ "${ans,,}" = 'y' ] && break
done
printf "\nkilling proc: %d\n" "$cmdpid"
kill $cmdpid # kill the PID
Example Use/Output
(without actually starting command above (as I have no clue what it is))
$ bash rununtil.sh
Would you like to stop the command (y/n)? k
Would you like to stop the command (y/n)? i
Would you like to stop the command (y/n)? l
Would you like to stop the command (y/n)? l
Would you like to stop the command (y/n)? Y
killing proc
Look things over and let me know if you have further questions.

Input to proprietary command prompt in shell script

I want to know how we can provide inputs to command prompts which change. I want to use shell scripting
Example where '#' is usual prompt and '>' is a prompt specific to my program:
mypc:/home/usr1#
mypc:/home/usr1# myprogram
myprompt> command1
response1
myprompt> command2
response2
myprompt> exit
mypc:/home/usr1#
mypc:/home/usr1#
If I understood correctly, you want to send specific commands to your program myprogram sequentially.
To achieve that, you could use a simple expect script. I will assume the prompt for myprogram is noted with myprompt>, and that the myprompt> symbol does not appear in response1 :
#!/usr/bin/expect -f
#this is the process we monitor
spawn ./myprogram
#we wait until 'myprompt>' is displayed on screen
expect "myprompt>" {
#when this appears, we send the following input (\r is the ENTER key press)
send "command1\r"
}
#we wait until the 1st command is executed and 'myprompt>' is displayed again
expect "myprompt>" {
#same steps as before
send "command2\r"
}
#if we want to manually interract with our program, uncomment the following line.
#otherwise, the program will terminate once 'command2' is executed
#interact
To launch, simply invoke myscript.expect if the script is in the same folder as myprogram.
Given that myprogram is a script, it must be prompting for input with something like while read IT; do ...something with $IT ...;done . Hard to say exactly how to change that script without seeing it. echo -n 'myprompt> would be the simplest addition.
can be done with PS3 and select construct
#!/bin/bash
PS3='myprompt> '
select cmd in command1 command2
do
case $REPLY in
command1)
echo response1
;;
command2)
echo response2
;;
exit)
break
;;
esac
done
Or with echo and read builtins
prompt='myprompt> '
while [[ $cmd != exit ]]; do
echo -n "$prompt"
read cmd
echo ${cmd/#command/response}
done

Display a progress bar or spinner while a command is running in bash script [duplicate]

This question already has answers here:
Using Bash to display a progress indicator [duplicate]
(12 answers)
Closed 7 years ago.
I have a bash script that ends as follows:
trap "exit" INT
for ((i=0; i < $srccount; i++)); do
echo -e "\"${src[$i]}\" will be synchronized to \"${dest[$i]}\""
echo -e $'Press any key to continue or Ctrl+C to exit...\n'
read -rs -n1
#show_progress_bar()
rsync ${opt1} ${opt2} ${opt3} ${src[$i]} ${dest[$i]}
done
I need a command or a function such as show_progress_bar() that put . (a dot) in the stdout every one second while rsync command is running (or a rotating / that rotates as / - \ | sequence while rsync is running).
Is it possible? Do I need to wrote such function myself, or there is available scripts for this purpose?
It's not pretty, but it works:
~$ while true; do echo -n .; sleep 1; done & sleep 3; kill %-; wait; echo;
[1] 26255
...[1]+ Terminated while true; do
echo -n .; sleep 1;
done
(exchange the "sleep 3" for your actual work)
It works like this:
The while loop runs as a background job.
Meanwhile, your work ("sleep 3" in my example) runs in the foreground.
When the work is done, "kill %-" kills the echo loop.
Then we wait for the job to terminate, and echo a newline, just in case.
Like I said, it's not pretty. And there's probably a much better way to do it. :)
EDIT: For example, like the answer here: Using BASH to display a progress (working) indicator

How to read input from the user in a bash subshell [duplicate]

Consider this bash script :
#!/bin/bash
while true; do
read -p "Give me an answer ? y/n : " yn
case $yn in
[Yy]* ) answer=true ; break;;
[Nn]* ) answer=false ; break;;
* ) echo "Please answer yes or no.";;
esac
done
if $answer
then
echo "Doing something as you answered yes"
else
echo "Not doing anything as you answered no"
fi
When run from the command line using :
$ ./script-name.sh
It works just as expected with the script waiting for you to answer y or n.
However when I upload to a url and attempt to run it using :
$ curl http://path.to/script-name.sh | bash
I get stuck in a permanent loop with the script saying Please answer yes or no. Apparently the script is receiving some sort of input other than y or n.
Why is this? And more importantly how can I achieve user input from a bash script called from a url?
Perhaps use an explicit local redirect:
read answer < /dev/tty
You can run it like this:
bash -c "$(curl -s http://path.to/script-name.sh)"
Since you're supplying content of bash script to bash interpreter. Use curl -s for silent execution.

Resources