Reexecute a part of a script in bash - 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

Related

Why is [[ "$input" == name1* || name2* ]] never false?

I'm a little befuddled with a script I've been writing - and would appreciate some help!
This is one of those cases where each command seems to work fine on their own, but not so when put together into a script.
Here's a gist of what I'm trying to do:
input=$1
single_func () {
command "$input"
}
multi_func () {
xargs < $input -n 1 single_func
}
if [[ "$input" == name1* || name2* ]];
then
single_func
elif [[ -f "$input" ]];
then
multi_func
else
echo "exiting"
exit
fi
The idea here is - if the script is invoked with ./script.sh input, if will run if the input starts with name1 or name2, using single_func. If the input provided doesn't start with name1 or name2, and is a file containing a list of items, elif will run (reason for -f) using multi_fuc, which is just single_func running with xarg on the provided file.
The 'single_func' component runs on the command line fine on its own (command "input"), and the 'multi_func' component runs fine with a test file (xargs < testfile.txt -n 1 ./single_func.sh). But when I put them together as above and try to run them together, only the first 'if' part works correctly. When provided with a file or some nonsense line not containing name1 or name2, the script simply exits without returning anything.
For the curious, I'm running entrez direct commands within the single_func block.
What am I doing wrong?
You need to write:
if [[ "$input" = name1* || "$input" = name2* ]]; then
Otherwise, the right-hand side of your || tests whether name2* is a non-empty string, which it always unconditionally is, making the statement always true.
If you don't want to repeat yourself (and your real use case is complex enough you can't just change it to if [[ "$input" = name[12]* ]]), use a case statement instead:
case $input in
name1*|name2*) echo "Either name1 or name2 prefix found";;
*) echo "Neither prefix found";;
esac

Bash script with options to run another script

I wish to create a simple bash script.
buildapp.sh -build1
buildapp.sh -build2
etc
the option build1/2/3/ etc call an external script depending on option.
So something like
buildapp.sh -build1 → script1.sh
buildapp.sh -build2 → script2.sh
I think this is what you are looking for:
if [ "$1" = "-build1" ]; then
path/to/script1.sh
elif [ "$1" = "-build2" ]; then
path/to/script2.sh
elif [ "$1" = "-build3" ]; then
path/to/script3.sh
else
echo "Incorrect parameter"
fi
Another option is to use getops (see An example of how to use getopts in bash)
Solution
#!/bin/bash
./script${1//[!0-9]/}.sh # './' is the path to scriptX.sh, you may need to adjust it
A very tiny solution, that works with every number, by simply referencing the numeric argument suffix. E.g. it calls ./script123.sh with -build123.
Solution (extended)
#!/bin/bash
if [[ '-build' == "${1//[0-9]/}" ]]
then
./script${1//[!0-9]/}.sh
fi
Extends the above version, so that it only runs ./scriptXXX.sh, if the argument prefix is -build

Bash Script with if, elif, else

Okay so this is an assignment so I will not put in the exact script here but I am really desperate at this point because I cannot figure something as basic as if's. So I am basically checking if the two arguments that are written in the command line are appropriate (user needs to type it correctly) or it will echo a specific error message. However, when I put in a command with 100% correct arguments, I get the error echo message from the first conditional ALWAYS (even if I switch around the conditional statements). It seems that the script just runs the first echo and stops no matter what. Please help and I understand it might be hard since my code is more of a skeleton.
if [ ... ]; then
echo "blah"
elif [ ... ]; then
echo "blah2"
else for file; do
#change file to the 1st argument
done
fi
I obviously need the last else to happen in order for my script to actually serve its intended purpose. However, my if-fy problem is getting in the way. The if and elif need to return false in order for the script to run for appropriate arguments. The if and elif check to see if the person typed in the command line correctly.
elif mean else-if. So it only will only be checked if the first statement returns false. So if you want to check if both are correct do.
if [ ... ] then
...
fi
if [ ... ] then
...
fi
When you care about checking both the first and second command line arguments for a single condition (i.e. they must both meet a set of criteria for the condition to be true), then you will need a compound test construct like:
if [ "$1" = somestring -a "$2" = somethingelse ]; then
do whatever
fi
which can also be written
if [ "$1" = somestring ] && [ "$2" = somethingelse ]; then
...
Note: the [ .... -a .... ] syntax is still supported, but it is recommended to use the [ .... ] && [ .... ] syntax for new development.
You can also vary the way they are tested (either true/false) by using -o for an OR condition or || in the second form. You can further vary your test using different test expressions (i.e. =, !=, -gt, etc..)

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.

Argument Checking Problem in Bash Script

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 :)

Resources