I'm pretty much brand new to linux, and I've written a simple bash shell script that asks a user for a number and then asks for another number and displays the sum and product of the numbers. I have no problems with this, but I'm wanting to loop the script.
For instances, I want to ask the user if they want to quit, and if they choose not to quit the script starts over and asks for two numbers again. If there's anyone out there who knows stuff about loops, could you help me out please? Thanks.
Here's my code:
#!/bin/bash
echo -n "Name please? "
read name
echo "enter a number."
read number1
echo "enter another number"
read number2
echo "Thank you $name"
let i=0
let i=$number1+$number2
let x=0
let x=$number1*$number2
echo "The sum of the two numbers is: $i"
echo "The product of the two numbers is: $x"
echo "Would you like to quit? Y/N? "
quit=N
while [ "$quit" = "Y" ]
do
clear
while ["$quit" != "Y" ]
do
echo "enter a number."
read number1
echo "enter another number"
read number2
echo "Thank you $name"
let i=0
let i=$number1+$number2
let x=0
let x=$number1*$number2
echo "The sum of the two numbers is: $i"
echo "The product of the two numbers is: $x"
echo "Would you like to quit? Y/N? "
#!/bin/bash
# Initialize quit so we enter the outer loop first time
quit="N"
# Loop while quit is N
while [ "$quit" = "N" ]
do
echo -n "Name please? "
read name
echo "enter a number."
read number1
echo "enter another number"
read number2
echo "Thank you $name"
let i=0
let i=$number1+$number2
let x=0
let x=$number1*$number2
echo "The sum of the two numbers is: $i"
echo "The product of the two numbers is: $x"
#reset quit - so we enter the inner loop first time
quit=""
#we want to repeat until quit is Y or N:
#while quit is not "Y" and quit is not "N"
while [ "$quit" != "Y" -a "$quit" != "N" ]
do
echo "Would you like to quit? Y/N?"
read quit
#Convert lower case y/n to Y/N
quit=`echo $quit | tr yn YN`
done
done
while [[ "$(read -p "Quit?" q;echo $q)" != "y" ]] ; do
echo okay, go on
done
Here is a quick example of loops:
#!/bin/env bash
let quit="N"
while [ $quit != "Y" ]; do
echo "To quit, enter Y:"
read quit
done
#!/bin/bash
function sumAndProd {
read -p "enter a number: " number1
read -p "enter another number: " number2
echo "Thank you $name"
sum=$((number1+number2))
prod=$((number1*$number2))
echo "The sum of the two numbers is: $sum"
echo "The product of the two numbers is: $prod"
}
read -p "Name please? " name
quit=N
while [[ "$quit" != Y ]]
do
sumAndProd
read -p "Would you like to quit? Y/N? " quit
done
This is more a code-review.
The main thing is, to put the repeated part in a function.
instead of i, x, you better use expressive names, maybe abbreviated like sum and prod.
if you follow an assignment (let a=0) with an assignment, without using your variable before, the first assignment is senseless.
The name of the user will not change - we need to ask for this just once.
while (cond) ; do {block} done # is a form of loop.
You can specify a prompt (-p) with read, so this will end in one instead of two lines.
per se, you will not find let very often. For arithmetic expressions, x=$((expression)) is far more common.
Since you don't reuse sum and prod, you don't even need a variable. Just echo The sum is $((number1+number2))
The easiest thing to do is to loop forever and break when the user quits:
while true
do
read -p "Continue to loop? " answer
[ "n" = "$answer" ] && break
done
echo "Now I'm here!"
The break command breaks you out of the current loop and continues right after the loop. No need for a flag variable.
By the way:
[ "n" = "$answer" ] && break
Is the same as:
if [ "n" = "$answer" ]
then
break
fi
Note the -p for the prompt in the read command. That way, you can prompt and read the variable at the same time. You can also use \c in echo statements to suppress the New Line, or use printf which doesn't do a NL:
read -p "What do you want? " wants #Prompt on the same line as the read
echo "What are your desires? \c" #Prompt on the same line as the read
read desires
printf "What are your hopes? " #Prompt on the same line as the read
read hopes
Hope this helps.
#!/bin/sh
while true
do
/var/www/bash/grep_ffmpeg.sh
sleep 15
done
loop with nohup
Related
Made a script that the user gives a "parameter" and it prints out if it is a file, directory or non of them. This is it :
#!/bin/bash
read parametros
for filename in *
do
if [ -f "$parametros" ];
then
echo "$parametros is a file"
elif [ -d "$parametros" ];
then
echo "$parametros is a directory"
else
echo " There is not such file or directory"
fi
exit
done
Altough i want the user to be allowed to give only one word as a parameter. How do i make this happen ? (For example if user press space after first word there would be an error message showing "wrong input")
#!/bin/bash
read parametros
if [[ "$parametros" = *[[:space:]]* ]]
then
echo "wrong input"
elif [[ -f "$parametros" ]]
then
echo "$parametros is a file"
elif [[ -d "$parametros" ]]
then
echo "$parametros is a directory"
else
echo " There is not such file or directory"
fi
See http://mywiki.wooledge.org/BashFAQ/031 for the difference between [...] and [[...]].
You have to use the $#. It gives the number of the parameters.
The code will be something like:
if [ "$#" -ne 1 ]; then
printf 'ERROR!\n'
exit 1
fi
First, I'm curious why you want to restrict to one word - a file or directory could have spaces in it, but maybe you are preventing that somehow in your context.
Here are a few ways you could approach it:
Validate the input after they enter it - check if it has any spaces, eg: if [[ "parametros" == *" " ]]; then...
Get one character at a time in a while loop, eg with: read -n1 char
Show an error if it's a space
Break the loop if it's 'enter'
Build up the overall string from the entered characters
1 is obviously much simpler, but maybe 2 is worth the effort for the instant feedback that you are hoping for?
My English is very bad, but i'm try to explain my problem.
I want to create a small program on bash in which the user will have to guess the numbers. But my program has no end.
I'm novice on bash scripting, but i try to get better everyday.
I'm using CentOS 7. I go to /usr/bin/local and create some file, give him chmod +x and open with gedit:
#!/usr/bin/bash
#This script should ask us our name and play the game "Guess the Number" with us.
echo "What is your name?"
read name
echo "Hello $name"
echo "I want to play $ name with you, you have to guess the number from 1 to 10)"
echo "Are you ready?"
read rdy
answer=$(( answer = $RANDOM % 10 ))
read -p "Enter your number: " variant
while [ $answer != $variant ]; do
if [ $answer -gt $variant ]; then
echo "Your number is bigger, try again"
elif [ $answer -lt $variant ]; then
echo "Your number is smaller, try again"
continue
fi
done
eternal "Your number is smaller/bigger"
until you press ctrl+c
What I need to do, please help. I know non amateurs don't likes novices but i need your help, show me my mistake, and i can get better. Thanks!
#!/bin/bash
echo "What is your name?"
read name
echo "Hello $name"
echo "I want to play with you, you have to guess the number from 1 to 10"
answer=$(( $RANDOM % 10 ))
while true
do
read -p "Enter your number: " variant
if [ "$answer" -gt "$variant" ]; then
echo "The number is bigger, try again"
elif [ "$answer" -lt "$variant" ]; then
echo "The number is smaller, try again"
else
break;
fi
done
echo "Yes, the answer was ${answer}"
You call
read -p "Enter your number: " variant
before the while loop.
Inside the loop you never change the variant, so the original value is re-used in the while condition. For Eternity.
You can start with variant=-1 and move the readinside the loop or do something like #xiawi.
I have a case statement like 1) 2) 3) ... as below where there are multiple if else condition on 1) format case.
I want to repeat the particular case on invalid condition.
When user select 1 first it ask for the name of the juice.
next it asks the availability. If yes it continues else asks for the count and does an operation. If the operation "exit 0" it just prints done. if the operation "exit 1" I wanted the loop to continue from the top ie from "name of the juice?"
1)
echo "Name of the Juice ?"
read juice
echo "Is it available? [Y/N]"
read deci
if [ "$deci" = "N" ]
then
echo "Continue.!"
else
echo "how many left in the warehouse ?"
read left
I have a command here which exits 0 or 1
if [ $? -eq 0 ]; then
echo "done"
else
<I have to continue from the start [ie;name of the juice]>
fi
fi
;;
echo "Name of the Pizza ?"
read juice
echo "Is it available? [Y/N]"
read deci
if [ "$deci" = "N" ]
then
echo "Continue.!"
else
echo "how many left ?"
read left
I have a command here which exits 0 or 1
if [ $? -eq 0 ]; then
echo "done"
else
<I have to continue from the start [ie;name of the juice]>
fi
fi
;;
Your code is a bit hard to read, but if I understand correctly, you want to loop within one of your cases and make decisions on whether to continue back to the start of that case statement, or whether to leave. That can be done by putting the contents of that particular case in an infinite loop with while : and then using continue to return to the beginning of the loop at any point, or using break to break out of the loop at any point.
Not passing on the remainder of your code, but you could handle case 1) of your case statement similar to:
1)
while :
do
printf "Name of the Juice?: "
read -r juice
printf "Is it available? [Y/N]: "
read -r deci
if [ "$deci" = "N" ] || [ "$deci" = "n" ]
then
printf "Continue.!\n"
else
printf "how many left in the warehouse?: "
read -r left
# I have a command here which exits 0 or 1
if [ $? -eq 0 ]; then
printf "done\n"
break ## break out of loop
else
continue
fi
fi
printf "Name of the Pizza?: "
read -r juice ## why juice - I thought this was pizza?
printf "Is it available? [Y/N]: "
read -r deci
if [ "$deci" = "N" ] || [ "$deci" = "n" ]
then
printf "Continue.!\n"
else
printf "how many left?: "
read -r left
# I have a command here which exits 0 or 1
if [ $? -eq 0 ]; then
printf "done"
break ## break out of loop
else
continue
fi
fi
done
;; # your case termination from where?
Please add further explanation of any additional requirements you have and post the complete script you are working on as A Minimal, Complete, and Verifiable example and I am happy to help further.
My Linux class just started to begin scripting and I am having trouble with one of my questions. The question is as follows: Use a script to take two numbers as arguments and output their sum using bc.
This is my first script. To get the script to execute you need to do chmod +x filename
This is what I have so far:
#!/bin/bash
read -p "Enter in a numeric value: " num1
read -p "Enter in a second numeric value: " num2
if [ $# -ne 2 ] ; then
echo "Enter in two numeric arguments"
else
echo "The sum of the entered values are: "
echo "$num1 + $num2"|bc
fi
I keep running into an error. When I enter in two values it displays "Enter in two numeric arguments". It shouldn't do that because if I enter in two values, the if statement will evaluate to false and go to the else statement. Is my logic wrong or am I approaching this the wrong way?
You can use a while loop and break.
n=0
ex=""
while [ 1 ]
do
read -p "Enter read in a numeric value" num
n=$(( n + 1))
if [[ $n -eq 2 ]]
then
ex=${ex}${num}
echo "Sum of the two values are"
echo ${ex} | bc
break
else
ex=$num" + "
fi
done
I'm new to linux and to bash programming/scripting as well.
Anyhow, I wanted to make a bash script that will do a few things:
will get input on which files to copy
will get the dest folder
will ask wether to copy or move
will do the desired operation
will ask at the end if to continue for another action or not
Now, as for parts 2,3,5 I'm ok but part 1 is kinda problematic.
So, here is the script and I hope that you could enlighten me on where I am wrong and why :)
#! /bin/bash
#beginning
clear
f=1
Beginning()
{
echo "HELLO $USER , THIS PROGRAM WILL COPY THE FILES YOU WANT TO YOUR DESIRED DESTINATION DIRECTORY"
echo -n "please enter the filname/s you want to copy (up to 6 files at a time): ";
echo
EnteringF
}
EnteringF()
{
echo " filename$f : ";
read cop$f
Confirm
}
Confirm()
{
echo "do you wish to copy another file (y/n)?";
read ans
if [ "$ans" = "y" ] || [ "$ans" = "Y" ]; then
f=$[sum=$f+1]
EnteringF
elif [ "$ans" = "n" ] || [ "$ans" = "N" ]; then
Destination
else
echo " invalid choice please try again "
Confirm
fi
}
Destination()
{
echo -n "now please enter the destination folder:";
read dest;
CopyMove
}
CopyMove()
{
echo -n "Do you want to copy or move the files/s? please enter c/m? ";
read choice;
if [ "$choice" = "c" ] || [ "$choice" = "C" ]; then
cp "$cop$f" "$dest";
echo "copied successfully"
UseAgain
elif [ "$choice" = "m" ] || [ "$choice" = "M" ] ; then
mv [ "$files" + "$f" ] "$dest"
echo "moved successfully"
UseAgain
else
echo " invalid choice please try again ";
CopyMove
fi
}
UseAgain()
{
echo "Do you want to use the program again y/n?";
read confirm
if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
Beginning
UseAgain
elif [ "$confirm" = "n" ] || [ "$confirm" = "N" ]; then
End
else
echo "invalid choice please try again"; UseAgain
fi
}
End()
{
clear
echo "THANK YOU $USER FOR USING THIS PROGRAM :-)"
}
Beginning
Now my main problem is that no data is recorded to cop variable, and therefore cp has nothing to copy.
Maybe I should use some other loop, but I still don't know how to use the others.
You'd want to use an array. I've rewritten some parts of your code:
#!/bin/bash
clear
f=0
cop=()
abort() {
echo >&2 "Something went wrong ($#)."
echo >&2 "Do you have a banana jammed in the keyboard?"
exit 1
}
Beginning() {
echo "HELLO $USER , THIS PROGRAM WILL COPY THE FILES YOU WANT TO YOUR DESIRED DESTINATION DIRECTORY"
echo "please enter the filename/s you want to copy:"
EnteringF
}
EnteringF() {
local i=$((${#cop[#]}+1))
IFS= read -r -e -p " filename$i: " f || abort "EnteringF"
cop+=( "$f" )
Confirm
}
Confirm() {
local ans
read -e -p "do you wish to copy another file (y/n)? " ans || abort "Confirm"
if [[ "${ans,,}" = y ]]; then
EnteringF
elif [[ "${ans,,}" = "n" ]]; then
Destination
else
echo " invalid choice please try again "
Confirm
fi
}
Destination() {
IFS= read -r -e -p "now please enter the destination folder: " dest || abort "Destination"
CopyMove
}
CopyMove() {
read -r -e -p "Do you want to copy or move the file/s? please enter c/m? " choice || abort "CopyMove"
if [[ "${choice,,}" = c ]]; then
if cp -v -- "${cop[#]}" "$dest"; then
echo "copied successfully"
else
abort "cp"
fi
UseAgain
elif [[ "${choice,,}" = m ]] ; then
if mv -v -- "${cop[#]}" "$dest"; then
echo "moved successfully"
else
abort "mv"
fi
UseAgain
else
echo " invalid choice please try again "
CopyMove
fi
}
UseAgain() {
read -e "Do you want to use the program again y/n? " confirm || abort "UseAgain"
if [[ "${confirm,,}" = y ]]; then
Beginning
UseAgain
elif [[ "${confirm,,}" = "n" ]]; then
End
else
echo "invalid choice please try again";
UseAgain
fi
}
End() {
clear
echo "THANK YOU $USER FOR USING THIS PROGRAM :-)"
}
Beginning
I'm not even sure it works, when I tried to run it I had a black screen with a scary prompt asking me what file I wanted to copy or move. I was expecting a pony or something really cool like a cat playing piano. But no. I didn't know what file I wanted to move, actually. I'm not even sure I wanted to move a file. If I had wanted to move a file, I would have used mv directly. I've used a few bashisms for you to dig.
Regarding your question about the variable cop, I used an array, so all the problems are gone at once!
More importantly, there's a huge design flaw in your program: recursion! it's terrible. You're stacking at each step, never releasing the stack. You should really think your design again! Look: if you call your program lol_pony_cat, and if you type this in a terminal:
yes '42' | ./lol_pony_cat
you'll soon obtain
Segmentation fault
That's because:
We start in Beginning
We go in EnteringF and we're prompt for a file name: we enter 42
We go in Confirm and we're prompt for y/n, but we answer an invalid 42, so
We go in Confirm and we're prompt for y/n, but we answer an invalid 42, so
We go in Confirm and we're prompt for y/n, but we answer an invalid 42, so
We go in Confirm and we're prompt for y/n, but we answer an invalid 42, so
We go in Confirm and we're prompt for y/n, but we answer an invalid 42, so
We go in Confirm and we're prompt for y/n, but we answer an invalid 42, so
We go in Confirm and we're prompt for y/n, but we answer an invalid 42, so
We go in Confirm and we're prompt for y/n, but we answer an invalid 42, so
We go in Confirm and we're prompt for y/n, but we answer an invalid 42, so
We go in Confirm and we're prompt for y/n, but we answer an invalid 42, so
We go in Confirm and we're prompt for y/n, but we answer an invalid 42, so
We go in Confirm and we're prompt for y/n, but we answer an invalid 42, so
We go in Confirm and we're prompt for y/n, but we answer an invalid 42, so
We go in Confirm and we're prompt for y/n, but we answer an invalid 42, so
We go in Confirm and we're prompt for y/n, but we answer an invalid 42, so
We go in Confirm and we're prompt for y/n, but we answer an invalid 42, so
We go in Confirm and we're prompt for y/n, but we answer an invalid 42, so...
like this until we reach a stack overflow.
Good luck.