I am a newbie to stack overflow so please bear with the formatting
It is a genuine problem
I am creating a program to copy ,remove and move a file but still cannot resolve the echo error that bugs it, what should i do?
I have read the other related question which tells to include a ; but this too has not resolved the situation
#!/bin/bash
echo "Menu "
echo "1. Copy a File "
echo "2. Remove a file "
echo "3. Move a file"
echo "4. Quit"
echo "Enter ur Choice \c"
read Choice
case " $Choice " in
1. echo "Enter File name to copy \c"
read f1
echo " Enter File name \c "
read f2
if [ -f $f1 ]
then
cp $f1 $f2
else
echo "$f1 does not exist"
fi
;;
2. echo "Enter the File to be removed "
read r1
if [ -f $r1 ]
then
rm -i $r1
else
echo "$r1 file does not exist "
fi
;;
3.
echo "Enter File name to move \c"
read f1
echo "Enter destination \c "
read f2
if [ -f $f1 ]
then
if [ -d $f2 ]
then
mv $f1 $f2
fi
else
echo "$f1 does not exist"
fi
;;
4.
echo "Exit......."
exit;;
esac
ERRORS
./script13.sh: line 10: syntax error near unexpected token `echo'
./script13.sh: line 10: ` 1. echo "Enter File name to copy \c " '
root#Kalilinux1:~/bin#
You lack the parenthesis, so :
#!/bin/bash
echo "Menu "
echo "1. Copy a File "
echo "2. Remove a file "
echo "3. Move a file"
echo "4. Quit"
read -p "Enter ur Choice >>> "
case " $Choice " in
1) echo "Enter File name to copy \c"
read f1
echo " Enter File name \c "
read f2
if [ -f $f1 ]
then
cp $f1 $f2
else
echo "$f1 does not exist"
fi
;;
2) echo "Enter the File to be removed "
read r1
if [ -f $r1 ]
then
rm -i $r1
else
echo "$r1 file does not exist "
fi
;;
3)
echo "Enter File name to move \c"
read f1
echo "Enter destination \c "
read f2
if [ -f $f1 ]
then
if [ -d $f2 ]
then
mv $f1 $f2
fi
else
echo "$f1 does not exist"
fi
;;
4)
echo "Exit......."
exit;;
esac
Instead of 1. in line 10, you should use 1). The correct way to do a case statement is:
case "$Choice" in
1) ...
;;
2) ...
;;
Also, remove the spaces in " $Choice ".
Related
I am trying to make a simple calculator. I am sure if you even just glanced at this code you will see what I am trying to do.
Enter a number, then choose an operand, then vim should print out a table up to 15 with your number and operand...
Maybe this method is silly, trying to nest a load of loops in nested if statements. But I am new to bash.
The error is 'Unexpected token near else' line 24 but I feel there is a fundamental issue with the nests I do not understand.
Here is current code.
#!/bin/bash
choice=6
read -p "Enter a number bruv" num
#choose operand.
echo "Now choose an operand comrade"
#choices
echo "1. *"
echo "2. +"
echo "3. -"
echo "4. /"
echo "5. ^"
echo -n "Please choose [1,2,3,4,5]"
while [ $choice -eq 6 ]; do
read choice
if [ $choice -eq 1 ] ; then
for((i=0;i<=15;i++))
do
echo -n "$i * $num = $[ $i * $num ] "
echo " "
else
if [ $choice -eq 2 ] ; then
for((i=0;i<=15;i++))
do
echo -n "$i + $num = $[ $i + $num ] "
echo " "
else
if [ $choice -eq 3 ] ; then
for((i=0;i<=15;i++))
do
echo -n "$i - $num = $[ $i - $num ] "
echo " "
else
if [ $choice -eq 4 ] ; then
for((i=0;i<=15;i++))
do
echo -n "$i / $num = $[ $i / $num ] "
echo " "
else
if [ $choice -eq 5 ] ; then
for((i=0;i<=15;i++))
do
echo -n "$i ^$num = $[ $i ^$num ] "
echo " "
else echo "Please choose between 1 and 5!!!"
echo "1. *"
echo "2. +"
echo "3. -"
echo "4. /"
echo "5. ^"
echo -n "Please choose [1,2,3,4,5]"
fi
fi
fi
fi
fi
done
Would it be better to implement this?
# !/bin/bash
# Take user Input
echo "Enter number : "
read a
# Input type of operation
echo "Enter Choice :"
echo "1. Addition"
echo "2. Subtraction"
echo "3. Multiplication"
echo "4. Division"
echo "5. Power"
read ch
# Switch Case to perform
# calulator operations
case $ch in
1)res=`for((i=0;i<=15;i++))
do
echo -n "$i - $num = $[ $i - $num ] "
echo " "`
;;
2)res=`for((i=0;i<=15;i++))
do
echo -n "$i - $num = $[ $i - $num ] "
echo " "`
;;
3)res=`for((i=0;i<=15;i++))
do
echo -n "$i - $num = $[ $i - $num ] "
echo " "`
;;
4)res=`for((i=0;i<=15;i++))
do
echo -n "$i - $num = $[ $i - $num ] "
echo " "c`
;;
esac
echo "Result : $res" ```
Here is a solution, using a function:
#! /bin/bash
ITER_MAX=15
show_values() # n op
{
local n=$1 op=$2
for ((i=0; i<=ITER_MAX; i++)); do
((i>0)) && echo -n " ; "
echo -n "$i $op $n = $((i $op n))"
done
echo
}
# Take user Input
read -p "Enter number : " a
# Input type of operation
echo "Enter Choice (Ctrl+C to stop):"
PS3=">> "
select ch in Addition Subtraction Multiplication Division Power ; do
case "$ch" in
Add*) op="+" ;;
Sub*) op="-" ;;
Mul*) op="*" ;;
Div*) op="/" ;;
Pow*) op="**" ;;
*) echo "Bad choice, abort" >&2 ; break ;;
esac
show_values "$a" "$op"
done
Some explanations:
(( )) is arithmetic evaluation and $(( )) is arithmetic expansion
((i>0)) && echo -n " ; " is equivalent to if ((i>0)); then echo -n " ; " ; fi
read -p "Enter number : " a is equivalent to echo -n "Enter number : " ; read a
about select, see help select in your bash terminal.
Use https://www.shellcheck.net/
Line 20:
for((i=0;i<=15;i++))
^-- SC1009: The mentioned syntax error was in this for loop.
^-- SC1073: Couldn't parse this arithmetic for condition. Fix to allow more checks.
Line 21:
do
^-- SC1061: Couldn't find 'done' for this 'do'.
Line 24:
else
^-- SC1062: Expected 'done' matching previously mentioned 'do'.
^-- SC1072: Unexpected keyword/token. Fix any mentioned problems and try again.
An alternate take:
read -p "Enter a number and an operator: " -a a
for n in {1..15}; do printf "%+10s\n" $((${a[#]} $n)); done
-p tells read to supply a prompt. -a reads into an array (named a here).
{1..15} is built-in bash sequence syntax.
%+10s tells printf to space-pad/right justify out to 10 characters.
${a[#]} is replaced with all the elements of the array - the number and then operator.
$(( ... )) does arithmetic processing and replaces itself with the result (as a string).
So if you enter "10 *" then $((${a[#]} $n)) processes 10 * 1 the first time, so printf "%+10s\n" $((${a[#]} $n)) outputs " 10" with a trailing newline character. Then the loop replaces the 1 with the next number on each iteration, up to 15. This also allows other operators, such as % for modulus, but will crash if something invalid is given.
If you want error checking -
while [[ ! "${a[*]}" =~ ^[0-9][0-9]*\ ([*/+-]|\*\*)$ ]]
do read -p "Enter a, integer and an operator (one of: + - * / **) " -a a
done
for n in {1..15}; do printf "%+10s\n" $((${a[#]} $n)); done
If you want floating point math, try bc:
while [[ ! "${a[*]}" =~ ^[0-9]+.?[0-9]*\ ([*/+-]|\*\*)$ ]]
do read -p "Enter a, integer and an operator (one of: + - * / **) " -a a
done
for n in {1..15}; do printf "%+15s\n" $(bc -l <<< "scale=3;${a[#]} $n"); done
Personally, I'd put the inputs on the command line. Less futzy, though it might require quoting the * operator, depending on how you run it and what's in the directory.
#!/bin/bash
me=${0##*/}
use="
use: $me {number} {operator} [iterations] [scale]
Numbers may include one decimal point.
Operators must be one of: + - * / **
"
while getopts "n:o:i:s:" arg
do case $arg in
n) n="$OPTARG" ;;
o) o="$OPTARG" ;;
i) i="$OPTARG" ;;
s) s="$OPTARG" ;;
*) printf "%s\n" "Invalid argument '$arg' $use";
exit 1;;
esac
done
[[ -n "$n" && -n "$o" ]] || { echo "$use"; exit 1; }
[[ "$n" =~ ^[0-9]+.?[0-9]*$ ]] || { printf "%s\n" "Invalid number '$n' $use"; exit 1; }
[[ "$o" =~ ^([*/^+-]|\*\*)$ ]] || { printf "%s\n" "Invalid operator '$o' $use"; exit 1; }
[[ "${i:=15}" =~ ^[0-9]+.?[0-9.]$ ]] || { printf "%s\n" "Invalid number '$i' $use"; exit 1; }
[[ "${s:=3}" =~ ^[0-9]+$ ]] || { printf "%s\n" "Invalid scale '$s' (must be an integer) $use"; exit 1; }
c=1
while ((c < i))
do printf "%+15s\n" $(bc -l <<< "scale=$s; $n $o $c")
((c++))
done
I commented the things I have problem.
and also, is there any other way I can exit my loop without using the exit command?.................
#!/bin/bash
while [ "$done" != "true" ] #this don't work
do
echo "Please enter one of the following options"
echo "1. Move empty files"
echo "2. Check file size"
echo "3. Which file is newer"
echo "4. File check rwx"
echo "5. Exit".
echo -n "Enter Choice: "
read scale # starting from this part for checking if user only inputs numbers 1-5 not working
if ! [[ "$scale" =~ ^[0-6]+$ ]]
then
echo "Invalid Input"
fi #up to this part is not working
read -r answer
case "$answer" in
1) ./move_empty
exit 55
;;
2) ./file_size
exit 0
;;
3) ;;
;;
4)
;;
5) done="true";;
esac
done
There are few things Which should be avoided
while [ "$done" != "true" ] --> while [ $done -ne 1 ] /* -ne is not equal to */
case "$answer" in --> case $answer in
Complete Code
var=0
flag=1
while [ $var -ne 1 ]
do
echo "Please enter one of the following options"
echo "1. Move empty files"
echo "2. Check file size"
echo "3. Which file is newer"
echo "4. File check rwx"
echo "5. Exit".
echo -n "Enter Choice: "
read scale
if [ $scale -gt 0 -a $scale -lt 6 ]
then
echo "valid Input, you can procees for switch "
else
echo "invalid input.. go again & give correct one "
flag=0
fi
if [ $flag -eq 1 ]
then
read -r answer
case $answer in
1) ./move_empty
#exit 55
break
;;
2) ./file_size
#exit 0
break
;;
3)
exit 0
;;
4)
;;
5) done="true";;
esac
fi
done
To come out from loop, without using exit command, use break. Here is the answer from man 1 bash
break [n]
Exit from within a for, while, until, or select loop.
If n is specified, break n levels. n must be ≥ 1. If n
is greater than the number of enclosing loops, all
enclosing loops are exited. The return value is 0
unless n is not greater than or equal to 1.
I am new to Linux bash scripting and I can't seem to find what I'm doing wrong. Here's my code. Entering number 2 and 3, after the prompt that I ask the user my code stops it doesn't continue to the IF ELSE statements. Thank you to those who will help!
#!/bin/bash
while true
do
clear
echo "Please enter one of the following options"
echo "1. Move empty files"
echo "2. Check file size"
echo "3. Which file is newer"
echo "4. File check rwx"
echo "5. Exit".
echo -e "Enter Choice:"
read answer
case "$answer" in
1) ./move_empty
exit 55 ;;
2) echo "Enter a filename"
read filename
if [ -f $filename ];
then ./file_size
fi
;;
3) echo "Enter first file:"
read filename
echo "Enter second file:"
read filename2
if [ ! -f "$filename" ];
then
echo "Supplied file name" $filename "does not exist";
if [ $filename" -nt $filename" ]; then
echo $filename "is newer"
exit 1fi
fi ;;
5) exit ;;
esac
done
If you have completed the check at ShellCheck.net, then you should have received:
$ shellcheck myscript
No issues detected!
If you didn't work it down to that point, you are not done. You have multiple quoting problems in your script and you compare $filename -nt $filename (which is always false). Small "attention to detail" issues that make a big difference. ShellCheck.net does a thorough job, but will not find logic issues, those are left to you. The cleanup of your quoting would look similar to:
#!/bin/bash
while true
do
clear
echo "Please enter one of the following options"
echo "1. Move empty files"
echo "2. Check file size"
echo "3. Which file is newer"
echo "4. File check rwx"
echo "5. Exit".
echo -n "Enter Choice: "
read -r answer
case "$answer" in
1) ./move_empty
exit 55
;;
2) echo -n "Enter a filename: "
read -r filename
if [ -f "$filename" ]
then
./file_size
fi
;;
3) echo -n "Enter first file: "
read -r filename
echo -n "Enter second file: "
read -r filename2
if [ ! -f "$filename2" ]
then
echo "Supplied file name $filename does not exist";
if [ "$filename" -nt "$filename2" ]; then
echo "$filename is newer"
exit 1
fi
fi
;;
5) exit
;;
esac
done
(note: you do not need echo -e as there are no backslash escaped characters to handle in your prompt, likely you intended -n to prevent the addition of a newline at the end of the prompt)
(also note: the use of clear, while fine for some terminals, will cause problems with others. Just be aware of the potential issue.)
If your then is on the same line with your conditional expression, e.g. if [ "$filename" -nt "$filename2" ]; then then a ';' is needed after the closing ']' to indicate a newline, otherwise, there is no need for a ';'.
Logic Problems
As discussed, the logic problems are not caught by ShellCheck and you must work though the code. It looks like you intended something like the following:
3) echo -n "Enter first file: "
read -r filename
echo -n "Enter second file: "
read -r filename2
if [ ! -f "$filename" ] || [ ! -f "$filename2" ]
then
echo "Supplied file '$filename' or '$filename2' does not exist";
exit 1
fi
if [ "$filename" -nt "$filename2" ]; then
echo "$filename is newer"
else
echo "$filename2 is newer"
fi
;;
You just have to take it line by line...
Look things over and let me know if you have further questions.
#!/bin/bash
helpFunc()
{
echo "Usage:
$0 --arg1
$0 --arg2 filename add/delete/replace "hi how are you"
$0 --help
"
}
function fileread() {
pwd
echo "Fileread Function"
if [ -f $filename ]
then
echo "file exists"
filename=$1
cat $1
case "$1" in
add|ADD)
read $1
if [$2 == 'add' ]
then
echo $3 >> $1
echo "add opeartion completed"
fi
shift
;;
delete|DELETE)
read $1
echo "echo delet string from file"
if [$2 == 'delete' ]
then
sed '/$3/d' $1
echo "add opeartion completed"
fi
shift
;;
replace|REPLACE)
read $1
if [ $4 == 'replace' ]
then
sed "s/$5/$6/g" "$1" > temp.txt
else
echo "Error: Cannot read $1"
fi
shift
;;
esac
shift
# return 0
else
echo "file not exist"
#return 1
fi
}
while [ $# ]
do
case "$1" in
--a)
if [ -z "$2" ]
then
echo "No argument supplied"
echo "hello" && echo " current process id : $$ "
else
echo -e "no need of sending arguments for --a"
helpFunc a;
exit 1
shift
fi
;;
--b)
if [ $( echo -e $2 | grep -c -E "^-" ) -eq 0 ]
then
fileName=$2
if [ -f "$fileName" ]
then
echo -e "The file is valid"
echo "Displaying $2 file..."
[ -z $fileName ] && { echo "File name missing"; exit 1; } || cat $fileName
case "$filename" in
add|ADD)
echo "adding"
fileread $3 $4
shift
;;
delete|DELETE)
echo "echo deleting"
fileread
shift
;;
replace|REPLACE)
echo "replacing"
fileread
shift
;;
esac
else
echo -e "please enter the valid file name or location"
helpFunc b;
exit 1
shift
fi
fi
esac
shift
done
exit 0
function file read should ignore the case inputs like ADD/add , delete/Delete etc.. and perform operations if i give the cmd line arguments and values and it should validate case sensitivity, file existence and path of the file
./script.sh -a -b /etc/opt/test.txt ADD "hi how are you" delete "i am fine" REPLACE "hi " "hey"
I want to make a multiple flags for my script. And didn't work like what I want it.
#!/bin/bash
function wherecpy
{
echo "Plaes write where the files are located: "
read placefile
cd $placefile
}
function funcpy
{
wherecpy
echo ""
echo "Please choose the following:"
echo ""
echo "1. Interactive copy, answer yes or no (y/n) before doing the copy"
echo "2. Make backups of existing destination files"
echo "3. Preserve file attributes"
echo "4. Do a recursively copy"
echo "5. Back to main menu"
echo ""
echo -n "Enter Your Selection: "
read selection
echo ""
case $selection in
1) a="-i" ;;
2) b="--backup" ;;
3) c="--preserve=all" ;;
4) d="-r" ;;
0) return 0 ;;
esac
echo "Type the name of the file you wish to copy/backup: "
read file
echo "Type the name of the destination file/directory: "
read dest
cp $a $b $c $d "$file" "$dest"
if [ $? == 0 ]; then
echo "Success"
else
echo "failed."
fi
}
I want it to work like that :
Please type in the source file(s) to copy:
File1 file2 file3
Please type in the destination:
dir1
Copy successful.
Press any key to return to main menu.
Use getopts :
There are many online resources you can take reference from