Reading Yes/No Option inside the loop, Does not work - linux

while read line
do
read -p "Are you alright? (y/n) " RESP
if [ "$RESP" = "y" ]; then
echo "Here i want to do something, but prompt does not wait for the answer"
else
echo "You need more bash programming"
fi
done < find-spam-send-php-ver2.log
==> This script does not work. It does not "wait" for the yes or not option.
Please I want this script to work. Please let me know, how do modify this.
I have seen this kind of similar things in many linux installation scripts.

I have not tested this but should work,
while read line <&3
do
read -p "Are you alright? (y/n):" RESP
if [ "$RESP" = "y" ]; then
echo "Here i want to do something, but prompt does not wait for the answer"
else
echo "You need more bash programming"
fi
done 3< find-spam-send-php-ver2.log

Related

What have i done wrong here? or is there a better alternitive to $answer?

Lately ive been busy playing around with bash on my linux operating system, and im also using it too sort files. But this does not seem to work. Is there an alternitive way of what im doing or is it wrong?
echo -n "Are you sure you would like to delete this/these files? [y/n]"
if [ $answer == "y" ]; then
echo -n "Which File would you like to delete?"
rm $answer
else
echo "canceled!"
fi
Check the following usage of "read" command
read -n1 -p "Are you sure you would like to delete this/these files? [y/n]: " answer
if [ "$answer" == "y" ]; then
read -p "Which File would you like to delete: " filename
rm $filename
else
echo "cancelled!"
fi

Repeat command in linux script if there is an error for google cloud console tools [duplicate]

I have a script and want to ask the user for some information, but the script cannot continue until the user fills in this information. The following is my attempt at putting a command into a loop to achieve this but it doesn't work for some reason:
echo "Please change password"
while passwd
do
echo "Try again"
done
I have tried many variations of the while loop:
while `passwd`
while [[ "`passwd`" -gt 0 ]]
while [ `passwd` -ne 0 ]]
# ... And much more
But I can't seem to get it to work.
until passwd
do
echo "Try again"
done
or
while ! passwd
do
echo "Try again"
done
To elaborate on #Marc B's answer,
$ passwd
$ while [ $? -ne 0 ]; do !!; done
Is nice way of doing the same thing that's not command specific.
You need to test $? instead, which is the exit status of the previous command. passwd exits with 0 if everything worked ok, and non-zero if the passwd change failed (wrong password, password mismatch, etc...)
passwd
while [ $? -ne 0 ]; do
passwd
done
With your backtick version, you're comparing passwd's output, which would be stuff like Enter password and confirm password and the like.
If anyone looking to have retry limit:
max_retry=5
counter=0
until $command
do
sleep 1
[[ counter -eq $max_retry ]] && echo "Failed!" && exit 1
echo "Trying again. Try #$counter"
((counter++))
done
You can use an infinite loop to achieve this:
while true
do
read -p "Enter password" passwd
case "$passwd" in
<some good condition> ) break;;
esac
done
while [ -n $(passwd) ]; do
echo "Try again";
done;

Smarter and more condensed method to match input variable in shell script?

I have a file with a list of numerous unique items, for this example I am using user ID's. The starting section of my script should display the list to the user running the script and allow them to chose one of the ID's. The script should then cross check the choice made by the user against the original file and if it matches it should provide a message advising of the match and continue with the script. If it does not match, the script should advise the user and exit.
My current script does this OK, but I was wondering if there is any way to make it a bit smarter/more condensed, perhaps using arrays? Current script:
This is my first post on this site so I apologies in advanced for any mistakes which have been made in the process of posting.
FILE=testfile
IDLIST="$(awk '{print $1}' $FILE)"
echo "$IDLIST"
echo "\nSelect one of the options"
read input
OUTPUT="$(for i in $IDLIST
do
if [[ $i = $input ]]
then
echo "Matched."
fi
done)"
if [[ -z $OUTPUT ]]
then
echo "Invalid choice."
exit 0
else
ID=$input
fi
echo "It is a match, continuing with script"
As you can imagine, there are many ways of doing this. One is using select instead:
PS3="Select an ID: "
select id in $(cut -d ' ' -f 1 testfile)
do
[[ -z $id ]] && echo "Pick a number" || break
done
echo "You selected $id"

Issue controlling script flow

I'm new to shell scripting, my script appears to be okay, but its the flow that I'm having an issue controlling. Could someone point out what silly mistake I've made please.
#! /bin/sh
echo "Are you sure youx want to delete $1? Answer y or n"
read ans
echo $ans
if $ans = "y"|"Y"
then
mv $1 /home/parallels/dustbin
echo "File $1 has been deleted"
else echo "File $1 has not been deleted"
fi
Make your if condition like this:
if [ "$ans" = "y" -o "$ans" = "Y" ]
There are a few things wrong with your script. Some are serious, some are less so.
First, the serious problems.
As guru suggested, you need to use square brackets to surround your if condition. This is because if only tests for the output of a condition, it doesn't perform actual string comparisons. Traditionally, a program called /bin/test, which was also called /bin/[ took care of that. These days, that functionality is built in to the shell, but /bin/sh still behaves as if it's a separate program.
In fact, you can do interesting things with if when you don't use square brackets for your condition. For example, if grep -q 'RE' /path/to/file; then is quite common. The grep -q command issues no output, but simply returns a "success" or "fail" that is detected by if.
Second serious problem is that you are echoing a status that may or may not be true. I call this a serious problem because ... well, log messages simply shouldn't make false claims. If the permissions are wrong for the file in $1, or the filename contains a space, then your mv command will fail, but the message will claim that it did not. More on this later.
Next, the less serious problems.
These are mostly style and optimization things.
First off, read on most platforms includes a -p option that lets you specify a prompt. Use this, and you don't need to include an echo command.
Second, your indenting makes it hard to see what the if construct is wrapping. This isn't a huge problem in a program this small, but as you grow, you REALLY want to follow consistent standards.
Third, you can probably get more flexibility in multiple-choice questions like this if you use case statements instead of if.
After all that, here's how I'd write this script:
#!/bin/sh
if [ "$1" = "-y" ]; then
ans=y
shift
elif [ -t 0 ]; then
read -p "Are you sure you want to delete '$1' (y/N) ? " ans
fi
case "$ans" in
Y*|y*)
retval=0
if [ -z "$1" ]; then
retval=64
echo "ERROR: you didn't specify a filename." >&2
if [ ! -f "$1" ]; then
retval=66
echo "ERROR: file '$1' not found!" >&2
elif mv "$1" /home/parallels/dustbin/; then
echo "File '$1' has been deleted" >&2
else
retval=$?
echo "ERROR: file '$1' could not be deleted!" >&2
fi
;;
*)
echo "ABORT: file '$1' has not been deleted" >&2
retval=4
;;
esac
exit $retval
Aside from what's mentioned above, here are some things in this code snippet:
[ "$1" = "-y" ] - if the user specifies a -y option, then we behave as if the question was answered with a "yes".
[ -t 0 ] - this tests whether we are on an interactive terminal. If we are, then it makes sense to ask questions with read.
Y*|y*) - in a case statement, this matches any string that begins with an upper or lower case "y". Valid affirmative responses would therefore be "Y", "yes", "yellow", etc.
[ ! -f "$1" ] - this tests whether the file exists. You can man test or man sh to see the various tests available in shell. (-f may not be the most appropriate for you.)
>&2 - at the end of a line, sends its output to "standard error" instead of "standard out". This changes how output will be handled by pipes, cron, etc. Errors and log data are often sent to stderr, so that stdout can be dedicated to a program's actual output.
mv "$1" ... - The filename is in quotes. This protects you in case the filename has special characters like spaces in it.
$retval - the values for this came from a best guess of the closest item in man sysexits.
retval=$? - this is the exit status of the most recently executed command. In this case, that means we're assigning mv's exit status to the variable $retval, so that if mv failed, the whole script reports the reason for the fail, as far as mv is concerned.
You can also convert the user response to either case and just check it for respective case like
read ans
ans=${ans,,} # make 'ans' lowercase, or use ${ans^^} for making it uppercase
if [ "$ans" = "y" ]
then
....
fi
Below is the perfect code with error handling included
#!/bin/sh
echo "Are you sure you want to delete $1? Answer y or n"
read ans
echo $ans
if [ $ans == "y" ] || [ $ans == "Y" ]
then
if [ -f $1 ]
then
mv $1 /home/parallels/dustbin
echo "File $1 has been deleted"
else
echo " File $1 is not found"
fi
else
echo "File $1 has not been deleted"
fi

Validate input from bash

I need to make a bash script that takes user input and does some validation.
The input is small. I just need to get a user choice "yes" or "no" and a file path and make sure the input is indeed a filepath and that he entered yes or no.
How can I validate the user input?
from your bash prompt type
help read
example:
step 1.
pete#ruthie ~ $ read -p "Yes or No :" ANSWER
Yes or No :Yes
pete#ruthie ~ $ echo $ANSWER
Yes
step 2.
case $ANSWER in
Y* | y* ) echo "ANSWER is yes" ;;
N* | n*) echo ANSWER is no;;
*) echo "Unclear Response" ;;
esac
ANSWER is yes
Or all on one line:
case $ANSWER in Y* | y* ) echo "ANSWER is yes" ;; N* | n*) echo ANSWER is no;; *) echo "Unclear Response" ;; esac
ANSWER is yes
So something vaguely like::
read -p "Enter File Name :" FILE_TO_CHECK
if [ ! -e "$FILE_TO_CHECK" ]; then
echo -e "There is no file called $FILE_TO_CHECK \n please check spelling"
else
echo "Congratulations found $FILE_TO_CHECK. "
ls -lah $FILE_TO_CHECK
read -p "Process $FILE_TO_CHECK ? Y or N : PROCEED
case $PROCEED in
Y* | y*)
##call function or system command to do something with this data
foo $FILE_TO_CHECK
;;
* )
echo -e "Note $USER\n No action taken by $0 on $FILE_TO_CHECK"
;;
esac
fi
The test command is your friend. You really need to learn its ways ASAP.
help [
and
help test
The "help bashthing" command is a great quick reminder.
see also: the Advanced Bash Scripting Guide (ABS)
http://tldp.org/LDP/abs/html/
FWIW:
This is a very simple example and wont accommodate much in the way of unexpected user input.
I would probably call functions for each step of this as then I could conditionally represent the user with another chance.
The case tests nested like this is plain ugly :) === hard to get neat and read later
There are other ways to achieve all this try zenity for a GTK style GUI.
The A.B.S is excellent but dont try to eat it all at once !

Resources