Argument Checking Problem in Bash Script - bash

So basically I am trying to check the arguments that are passed into the script. If it has three arguments and the third argument is a 1, then I want it to continue. I also want it to continue if it has four arguments and the third argument is not a 1.
So basically I thought that I could just do...
if ([ $# -ne 3 ] and [ "$3" -ne "2" ])
then
exit 0
fi
However it seems that Bash does not have and's to use for if's,so then I figured that I could just use nested if's, however now it's complaining still. So this is what I have currently...
if [ $# -ne 3 ]
then
if [ "$3" -ne "1" ]
then
echo "Improper number of arguments.
FORMAT make-csv-data <STUDY> <TAG> <MODE> <SELECT>
Select can be left off if you want all data (Mode=1)
"
exit 0
fi
fi
if [ $# -ne 4 ]
then
if [ "$3" -ne "2" ]
then
echo "Improper number of arguments.
FORMAT make-csv-data <STUDY> <TAG> <MODE> <SELECT>
Select can be left off if you want all data (Mode=1)
"
exit 0
fi
fi
So where am I going wrong? Can I not nest if statements in Bash? Is there a super-zen way of doing this that I'm missing altogether?
Thanks for the any help you could give me.
New Problem...
Now, for some reason or another, the code isn't working at all. There are no errors or anything, it just doesn't work. It doesn't check the number of arguments. I've run the script with no arguments at all and it just skips it like it's not even there.
Weird part is that I was sure that the code was working yesterday. Come back today, not so much. Any ideas on what the problem is? (Sorry, but I have to remove the accepted answer on this.)
if [[ $# = 3 && "$3" != "1" ]]
then
echo "Improper number of arguments.
FORMAT make-csv-data <STUDY> <TAG> <MODE> <SELECT>
Select can be omitted if all data is required (Mode=1)
"
exit 0
fi
if [[ $# > 4 ]]
then
echo "Improper number of arguments.
FORMAT make-csv-data <STUDY> <TAG> <MODE> <SELECT>
Select can be omitted if all data is required (Mode=1)
"
exit 0
fi
EDIT II:
There are a few things that the Bash shell isn't liking about this script that I'm trying to do. I'll probably end up rewriting it in another scripting language and do a few more things that I have in mind for the project. Thanks for the help in any case.

if [ $# -ne 3 -a "$3" -ne "1" ]; then
exit 0
fi
For reference
-a = and
-o = or
Or, you could just use use:
if [[ $# != 3 && "$3" != "1" ]]; then

Please see:
http://bash-hackers.org/wiki/doku.php/commands/classictest#and_and_or
and
http://bash-hackers.org/wiki/doku.php/syntax/ccmd/conditional_expression
Since you're just checking exit/return values with "if", you need to provide something, e.g. a command, that provides meaningful ones based on your tests. [ is such a command, another possibility is the [[ keyword.
The actual correct examples already were mentioned by scragar above, I don't want to just repeat them :)

Related

Explain Bash Script

Can someone please help me to understand this bash script? I am really struggling with first block and last block specifically if and then blocks of the code.
if [[ $# -ne 2 ]] ; then
echo 'Cluster name, Azure Subscription ID required as input arguments.'
echo 'Example usage: ./create_blob_container.sh <CLUSTER_NAME> <ARM_SUBSCRIPTION_ID>'
exit 1
fi
MAX_CHAR_CLUSTER_NAME=8
CLUSTER_NAME=${1}
ARM_SUBSCRIPTION_ID=${2}
ARM_STORAGE_ACCOUNT_TFSTATE_NAME=${CLUSTER_NAME}tfstate$(echo ${ARM_SUBSCRIPTION_ID}|cut -c1-
8)
RESOURCE_GROUP_NAME=stack-tfstate-rg
CONTAINER_NAME=tfstate
LOCATION=westeurope
SKU=Standard_LRS
ENCRYPTION_SERVICES=blob
if [ ${#CLUSTER_NAME} -gt ${MAX_CHAR_CLUSTER_NAME} ]; then
echo "ERROR: Project name is too long (${#CLUSTER_NAME} chars). Maximal number of allowed
chars is ${MAX_CHAR_CLUSTER_NAME}. Exiting..."
exit 1`enter code here`
fi
Thank you
The first block means if the number of the positional parametre passed to the script is not equals to 2 then the script will execute 2 echo and exit.
if [[ $# -ne 2 ]]
Here a link that might help you.
The last block means if the length of the string stored in the variable CLUSTER_NAME which is the first position parametre is greather than MAX_CHAR_CLUSTER_NAME which is 8
if [ ${#CLUSTER_NAME} -gt ${MAX_CHAR_CLUSTER_NAME} ]; then
Another link

Stumped: this script does not work as expected?

I'm stumped when writing a simple script.
Essentially the $u variable is does not take u=$USER. Here's the code:
#!/bin/bash
if [ $# > 0 ] ; then
u=$1
else
u=$USER
fi
echo $u
The fix
You have 2 equally viable options:
Use -gt
if [ $# -gt 0 ]
Use double brackets [[ (Does a lexicographic comparison but will work for this case)
if [[ $# > 0 ]]
Why?
When you did if [ $# > 0 ] the > was treated like an output redirection command similar to echo "foo" > file.txt. You might notice you have created a file named 0 someplace after executing:
if [ $# > 0 ]
When deciding between using [...] or [[...]] many find the answer is to use double brackets
Getting fancy
Now if what you'd really like to do is write a script that gives a default value to the u variable if none is provided by the first argument I would recommend using a neat bash syntax trick for implementing default values
u=${1:-${USER}}
I believe I found the answer using double brackets
#!/bin/bash
if [[ $# > 0 ]] ; then
u=$1
else
u=${USER}
fi
echo $u
Not sure I fully understand why it failed with single brackets.

Reexecute a part of a script in bash

I have a script which contains 4 parts.
So when I execute the script, the 4 parts will be installed. This is what I want. But it's possible there need to be an update. Than only 2 parts need to be executed. What's the most efficient way to perform this?
I had something like this but it's redundant:
if [ $1 = "-u" ]
then
#Part1
#Part2
elsif
#Part1
#Part2
#Part3
#Part4
fi
Is there a better way to define this?
As far as I have understood you're going to execute Part1 and Part2 in any case. So I would code it this way:
#Part1
#Part2
if [ "$1" != "-u" ] ; then
#Part3
#Part4
fi
or... using bash builtins:
#Part1
#Part2
if [[ $1 != "-u" ]] ; then
#Part3
#Part4
fi

Removing files in Unix using bash

I'm trying to delete a large amount of files from my computer, and I'm trying to write a bash script to do so using the rm command. What I want to know is how to do equality in bash, and why my code (posted below) won't compile. Thank you for your help!
#!/bin/bash
# int-or-string.sh
b="0000"
c="linorm"
f=500
e1=2
e2=20
e3=200
e4=2000
for i in {0..10000}
do
a=$(($f*$i))
if ["$i" -eq "$e1"]
then
b="000"
echo $b$
fi
if ["$i" -eq "$e2"]
then
b='00'
fi
if ["$i" -eq "$e3"]
then
b='0'
fi
if ["$i" -eq "$e4"]
then
b =''
fi
if [bash$ expr "$i" % "$e3$ -ne 0]
then
d = $b$c$a
rm d
fi
done
Shell scripts aren't compiled at all.
You need spaces after your [ and before your ].
if [ "$i" -eq "$e1" ]
There's an errant bash$ in there you probably don't want at all. It should probably be a $() operator:
if [ $(expr "$i" % "$e3") -ne 0 ]
You can't have spaces around the = in bash. For example, change b ='' to b='' and d = $b$c$a to d=$b$c$a.
echo $b$ looks like it should be echo $b.
Shell script does not compile it is a scripting language.
Try to fix this line :
if [bash$ expr "$i" % "$e3$ -ne 0]
Make it like below :
if [ $(expr "$i" % "$e3$") -ne 0 ]
You need spaces around the square brackets. The [ is actually a command, and like all commands needs to be delineated by white space.
When you set values for variables in shell, you do not put spaces around the equals signs.
Use quotation marks when doing comparisons and setting values to help delineate your values.
What happens if none of the if conditions are true, and $b isn't set.
What is the logic behind this code. It seems to be a bunch of random stuff. You're incrementing $ from 1 to 10000, but only setting the value of $b on only four of those values. Every 200 steps, you delete a file, but $b may or may not be set even though it's part of the file name.
Did you write this program yourself? Did you try to run it? What errors were you getting? Did you look at the lines referenced by those errors. It looks like you included the bash$ prompt as part of the command.
There were plenty of errors, and I've cleaned most of them up. The cleaned up code is posted below, but it still doesn't mean it will do what you want. All you said is you want to delete "a large amount of files" on your computer, but gave no other criteria. You also said "What I want to know is how to do equality in bash" which is not the question you stated in you header.
Here's the code. Note the changes, and it might lead to whatever answer you were looking for.
#!/bin/bash
# int-or-string.sh
b="0000"
c="linorm"
f=500
e1=2
e2=20
e3=200
e4=2000
for i in {0..10000}
do
a=$(($f*$i))
if [ "$i" -eq "$e1" ]
then
b="000"
elif [ "$i" -eq "$e2" ]
then
b='00'
elif [ "$i" -eq "$e3" ]
then
b='0'
elif [ "$i" -eq "$e4" ]
then
b=''
fi
if ! $(($i % $e3))
then
d="$b$c$a"
rm "$d"
fi
done
ERRORS:
Spaces around the [ and ]
The rm "$d" command was originallyrm dwhich would just remove a file namedd`.
if/then statement converted to if/else if.
Rewrote [ $(expr "$1" % "$e3") -ne 0 ].
No need for expr since BASH has $((..)) syntax.
No need for test command ([) since if automatically evaluates zero to true and non-zero to false.
Added quotes.

Bash, no-arguments warning, and case decisions

I am learning bash.
I would like to do a simple script that, when not arguments given, shows some message. And when I give numers as argument,s depending on the value, it does one thing or another.
I would also like to know suggestions for the best online manuals for beginners in bash
Thanks
if [[ $# -eq 0 ]] ; then
echo 'some message'
exit 0
fi
case "$1" in
1) echo 'you gave 1' ;;
*) echo 'you gave something else' ;;
esac
The Advanced Bash-Scripting Guide is pretty good. In spite of its name, it does treat the basics.
If only interested in bailing if a particular argument is missing, Parameter Substitution is great:
#!/bin/bash
# usage-message.sh
: ${1?"Usage: $0 ARGUMENT"}
# Script exits here if command-line parameter absent,
#+ with following error message.
# usage-message.sh: 1: Usage: usage-message.sh ARGUMENT
Example
if [ -z "$*" ]; then echo "No args"; fi
Result
No args
Details
-z is the unary operator for length of string is zero.
$* is all arguments.
The quotes are for safety and encapsulating multiple arguments if present.
Use man bash and search (/ key) for "unary" for more operators like this.
Old but I have reason to rework the answer now thanks to some previous confusion:
if [[ $1 == "" ]] #Where "$1" is the positional argument you want to validate
then
echo "something"
exit 0
fi
This will echo "Something" if there is no positional argument $1. It does not validate that $1 contains specific information however.
If there is not only 1 argument, then print usage and exit
if [[ $# != 1 ]] ; then
echo 'USAGE: bin/siege COOKIE'
exit 0
fi

Resources