I am writing a bash script which takes multiple user inputs. Before the script will take any action, I want to ensure that all values have been added by a user.
#/bin/bash
read -p "Please enter the domain Name: " domain
read -p "Please Enter path where you want to save your result: " path
if [[ -z "$domain" && "$path"]]; then
echo "You have not entered the Domain Name"
exit 1
else
echo "Do Something Here"
fi
I have checked with 1 user input, working fine, but when trying with 2 user inputs, I am getting an error.
./test.sh: line 5: unexpected token `;', conditional binary operator expected
./test.sh: line 5: syntax error near `;'
./test.sh: line 5: `if [[ -z "$domain" && "$path"]]; then'
Thanks!
Because you're using the [[ double brackets, you can use || to test if either of your conditions is true. In this case, your code would look like this:
#!/usr/bin/env bash
read -p "Please enter the domain Name: " domain
read -p "Please Enter path where you want to save your result: " path
if [[ -z "$domain" || -z "$path" ]]; then
echo "Either you have not entered the Domain Name, or you have not entered the path."
exit 1
else
echo "Do Something Here"
fi
Note that spaces around the brackets are necessary.
As others have pointed out, errors should be specific, so you should consider something like this:
if [[ -z "$domain" ]]; then
echo "You have not entered the Domain Name"
exit 1
elif [[ -z "$path" ]]; then
echo "You have not entered the path"
exit 1
fi
echo "Do something here"
It's a bit more verbose but gives the user more specific feedback.
You are getting syntax error because you forgot to put a space between "$path" and ] (bash uses spaces as delimiters).
If you want to fail when at least one condition is wrong, you should use the || (OR) operator.
#/bin/bash
read -p "Please enter the domain name: " domain
read -p "Please enter the path where you want to save your result: " path
if [[ -z "$domain" ]] || [[ -z "$path" ]] ; then
echo "You didn't enter the domain name or the save path"
exit 1
else
echo "Do something here"
fi
Related
So I am learning bash and wanted to make a script to 'automate' a collection of kali tools. Basically I do not understand why the if statement code is being triggered regardless if condition is true or false.
#!/bin/bash
#requires root or sudo priv
#check for a successful ping
target_ip=$1
nmap_opt = " "
#nmap options variables --
nmap_os="-O"
nmap_version="-sV"
nmap_udp="-sU"
nmap_stealth="-sS"
nmap_aggr="-A"
nmap_option_input_temp=""
ping $target_ip -c 5
if [ $? -eq 0 ]; then
echo "successful ping on" $target_ip
else
echo "ping unsuccessful, check VPN connection or host may be down"
exit 1
fi
read -p "enter pathway for nmap output: " nmap_file
read -p "detect os? (y/n) " nmap_option_input_temp
#add loops for y/n user input
if [[ ${nmap_option_input_temp} -eq "y" ]];
then
nmap_opt="${nmap_opt} ${nmap_os}"
elif [[ ${nmap_option_input_temp} -eq "n" ]];
then
nmap_opt=$nmap_opt
else
echo "invalid option"
fi
read -p "detect version? (y/n) " nmap_option_input_temp
#add loops for y/n user input
if [[ ${nmap_option_input_temp} -eq "y" ]];
then
nmap_opt="${nmap_opt} ${nmap_version}"
elif [[ ${nmap_option_input_temp} -eq "n" ]];
then
nmap_opt=$nmap_opt
else
echo "invalid option"
fi
echo "nmap selected option/s:" $nmap_opt
echo $nmap_option_input_temp
#starting nmap..
sudo nmap $nmap_opt -oN $nmap_file $target_ip
this is the nmap_opt variable echo out even when both inputs are 'n'
nmap selected option/s: -O -sV
Let me know if there is anything I missed in the explanation!
-eq is for integer comparisons. Use ==:
if [[ "${nmap_option_input_temp}" == y ]];
And fix your quotes. Fixed strings like y don't need to be quoted. Inside [[, variables don't need to be quoted, but IMO you should quote them anyway for consistency.
This error would be more easily spotted if you used the more conventional:
if [ "${nmap_option_input_temp}" -eq y ]; # Still incorrect!!
since you would get a nice error message.
Note that the fix with [ is slightly different, and you should use a single =:
if [ "${nmap_option_input_temp}" = y ];
The == operator is a bashism which does not really add any value. But really, you should not be using if/elif at all here. This is the perfect place for a case statement:
case "${nmap_option_input_temp}" in
y) nmap_opt="${nmap_opt} ${nmap_os}";;
n) ;;
*) echo "invalid option" >&2 ;;
esac
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?
Bash newbie question: I'd like to have this script echo out only users from a given list that are valid user IDs, and not echo the invalid ones.
Here's what I have so far:
#!/bin/bash
while IFS= read -r line
do
id "$line"
if [ $? -eq 1 ] ; then
echo $line
else
echo "$line is not valid user ID" >&2
fi
done < "$1"
Instead, it is echoing out the results of 'id' as well as the text "is not valid user ID"
uid=17931(wwirls) gid=100000(all_usr) groups=100000(all_usr),12(everyone),62(netaccounts),701(1)
wwirls is not valid CruzID
id: smak: no such user
smak
Ideally, it'd echo results like:
wwirls
otheruserid
admin
Your help is appreciated!
id "$line" &> /dev/null
is probably the smallest change that will do what you want. That says to send the output of id (including any error messages) to the bit bucket (/dev/null). However, the sense of your test is backwards - $? is 0 on success, and 1 on failure.
Now, as it happens, if automatically looks at $?. So you can shorten this to:
if id "$line" &> /dev/null # Find out if the user exists, without printing anything
then
echo "$line" # The user exists (`id` succeeded)
else
echo "$line is not valid user ID" >&2 # No such user
fi
Edit 2 If you don't need the not valid output, you can replace the whole if..fi block with
id "$line" &> /dev/null && echo "$line"
If the command before && succeeds, bash runs the command after &&.
Can somone help me with this: so i have this script
#!/bin/bash
echo -n "Enter a value for X:(999 to exit): "
read x
until [[ $x == 999 ]]
do
echo -n "Enter a value for Y: "
read y
echo "X="$x
echo "Y="$y
((a=y+x))
echo "X+Y="$a
((s=y-x))
echo "X-Y="$s
((m=y*x))
echo "X*Y="$m
((d=y/x))
echo "X/Y="$d
((m=y%x))
echo "X%Y="$m
echo -n "Enter a value for X:(999 to exit): "
read x
if [[ $x == 999 ]];
then
exit 0
fi
done
exit 0
but i didnt know how to write the rest of it, the missing thing is:
Use the two command line arguments when the script starts if the user supplied them, and then prompt for more numbers to continue in the loop.
Am guessing the arguments you are looking from the user are x and y values. The easiest way to check if user provided arguments is to use $# which gets you the number of arguments given by the user.
So use it like this:
if [ "$#" -eq 2 ]; #2 arguments provided by user
then
x=$1
...
fi
then, elif, else statement that I have programmed in a bash script. I know that it works because I can run the same command in the terminal interface and see that it is doing what I want it to do. However when I run it in a script it seems to always jump to the else statement and not detect anything. Can anybody help explain why this is so? Here is my script code:
if [ -e "$1" ]
then
for line in `samtools view -H $1`
do
if [[ "$line" == *NCBI-Build-36\.1* ]]
then
echo "hg18"
break
elif [[ "$line" == *hg19* ]]
then
echo "hg19"
break
else
echo "Reference was not found, manual entry required: "
read ans
echo "$ans"
break
fi
done
else
echo -e "Usage: \e[1;32mreadRef.sh \e[1;36mbamfile.bam"
fi
No matter what file I plug in it always skips to the else and asks me for manual entry.
Here is the command I ran on terminal:
for line in `samtools view -H $bignormal`; do if [[ "$line" == *NCBI-Build-36\.1* ]]; then echo "YES - $line"; else echo "NO - $line"; fi; done
And the output is like this:
NO - #HD
NO - VN:1.0
NO - GO:none
NO - SO:coordinate
NO - #SQ
NO - SN:1
NO - LN:247249719
YES - AS:NCBI-Build-36.1
YES - UR:http://www.bcgsc.ca/downloads/genomes/9606/NCBI-Build-36.1/bwa_ind/genome/
NO - SP:Homo
NO - sapiens
.
.
.
Why is the script not detecting the string I am looking for, but it is in terminal?
EDIT:
I tried what Charles said, this is the output:
:+'[' -e /projects/rcorbettprj2/DLBCL/CNV/RG065/normal/A01440_8_lanes_dupsFlagged.bam ']'
::+samtools view -H /projects/rcorbettprj2/DLBCL/CNV/RG065/normal/A01440_8_lanes_dupsFlagged.bam
:+for line in '`samtools view -H $1`'
:+case "$line" in
:+echo 'Reference was not found, manual entry required: '
Reference was not found, manual entry required:
:+read ans
I think your code has a logic error nobody's spotted yet. I'm not sure, since you haven't told us what the script's supposed to be doing, but it looks to me like what you want is to ask for manual entry only if you don't find a match to either of your patterns anywhere in the output, but what you're actually doing is examining only the first word of output for a match. And from your sample output, the first word is "#HD", which doesn't match either pattern, so the script is doing exactly what I'd expect.
Now, assuming I'm right and that the point is to look for either pattern anywhere in the output, you can actually simplify things a bit. Mainly, you don't need the loop, you can just do a single comparison to look for the pattern in the entire output at once:
#!/bin/bash
if [ -e "$1" ]
then
output="$(samtools view -H "$1")"
if [[ "$output" == *NCBI-Build-36.1* ]]
then
echo "hg18"
elif [[ "$output" == *hg19* ]]
then
echo "hg19"
else
read -p "Reference was not found, manual entry required: " ans
echo "$ans"
fi
done
else
echo -e "Usage: \e[1;32mreadRef.sh \e[1;36mbamfile.bam"
fi