Linux : From where the value will be fed to the linux script file - linux

I am working on a existing build script where the script file contains these (Some part )
As part of the build process , i need to run this script file .
#!/bin/sh
if [ -z $1 ]; then
help
elif [ $1 == 'test' ]; then
test
Could anybody please let me know what does this mean and form where does the value will be fed from ??

If the first argument ($1) is "empty" then call help otherwise if it's "CheckIn" then call CheckIn.
This is very basic stuff, you should read the manual page.

Actually this script says:
If the script is called without arguments, then call function help
Else if the first argument passed to the script is CheckIn then call function CheckIn
An example could be:
#!/bin/sh
CheckIn() {
echo "CheckIn called!!";
}
help () {
echo "Help called!!";
}
if [ -z $1 ]; then
help
elif [ $1 == 'CheckIn' ]; then
CheckIn
fi
So if this script is named, i.e test.sh the output of running it would be:
sh test.sh
output: Help called!!
sh test.sh CheckIn
output: CheckIn called!!
Finally please note that in your logged-in user shell there can be built in scripts named help and CheckIn. In this case these scripts/commands will be called and there is no need for functions named help/CheckIn to be present.

You should call the script with an argument:
/path/to/script.sh argument
If there are more arguments, they are referred to as $1, $2, ...

$1 refers to the first argument that is passed to your script on the command line. For example, if your script is called myscript.sh and you run it with myscript.sh foo, then $1 is foo.
if [ -z $1 ] is an if-statement which checks if the length of $1 is zero. If so, it runs the help function which must be defined (or sourced) somewhere above this point in your script.
elif [ $1 == 'CheckIn' ] checks whether $1 is CheckIn and if so, runs the CheckIn function.
See:
Bash Guide for Beginners: Introduction to if

Related

How to read the first line user types into terminal in bash script

I'm trying to write a script where to run the script, the user will type something along the lines of
$./cpc -c test1.txt backup
into the terminal, where ./cpc is to run the script, -c is $option, test1.txt is $source and backup is $destination.
How would I assign the values typed in to the terminal to use them in my script, for example in
if [[ -z $option || -z $source || -z $destination ]]; then
echo "Error: Incorrect number of arguments." (etc)
as when checking the script online the following errors return: 'option/source/destination is referenced but not assigned.'
Sorry in advance if any of this doesn't make sense, I'm trying to be as clear as possible
The arguments are stored in the numbered parameters $1, $2, etc. So, just assign them
option=$1
source=$2
destination=$3
See also man getopt or getopts in man bash.

Why can't get the shell script's parameter count in a function

I'm confused about why can't get the script's parameter count in a function, could anybody help me? thanks in advance:)
test.sh
#!/bin/bash
check(){
echo $#
if [ $# -lt 2 ]; then
echo "Argument missing"
exit 1
fi
}
echo $#
check
Run:
./test.sh aa bb
output:
2
0
Functions have their own local copies of the argument variables, including $#. They are related to the arguments of the function, and the equivalents at the script level are shadowed. If you want to get the script's argument variables then you will need to either store them somewhere else first or pass them to the function.
check "$#"

utterly confused regarding bash script command line arguments

I have the following bash script file callee.sh which is being called from another script file caller.sh.
The callee.sh is as follows:
if [ $1 -eq 1 ];
then
echo inside $1
source ~/MYPROGRAMSRC/standAloneWordCount.sh $2
#echo "inside standalone branch"
#echo $1
elif [ $1 -eq 2 ];
then
#echo "inside distributed branch"
#echo $1
else
echo invalid option for first argument-\n Options:\n "distributed"\n or\n "standalone"\n
fi
As most people might be able to tell, this is a script I use to decide whether to run hadoop in distributed or standAlone mode depending on the arguments.
This script is called from caller.sh as follows
source callee.sh $2 $counterGlobal
where $2 is a number either 1 or 2 and $counterGlobal is some integer.
My problem is that the if condition in callee.sh never evaluates to True and hence my script standAloneWordCount.sh which I call from within callee.sh is never called. I am running with bash shell and have tried many variants of the if statement like:
if [ $(($1 == 1 )) ] -- (1)
In an echo statement just above the line -- (1) , the expression $(($1 == 1)) evaluates to 1 so I am baffled as to why I am unable to satisfy the if condition.
Also I keep getting the error where it says:
syntax error near unexpected token `else'
if anyone could help me out with these two errors, it would be much appreciated. As I've run out of ideas.
Thanks in advance!
have tried many variants of the if statement like:
if [ $(($1 == 1 )) ]
You should instead be saying:
if (($1 == 1)); then
...
fi
Regarding the Syntax error near unexpected tokenelse'`, it's not because of any code that you've shown above. It seems to originate from some other portion of your script.
If you're using bash, try using double square brackets:
if [[ $1 -eq 1 ]]; then
echo "inside 1"
fi
As for the syntax error, you need quotes around your text (which also means escaping the existing quotes or use single quotes):
echo -e "invalid option for first argument-\n Options:\n \"distributed\"\n or\n \"standalone\"\n"
The -e flag is there to let bash know you want the \n to evaluate to a newline.

Script parameters in Bash

I'm trying to make a shell script which should be used like this:
ocrscript.sh -from /home/kristoffer/test.png -to /home/kristoffer/test.txt
The script will then ocr convert the image file to a text file. Here is what I have come up with so far:
#!/bin/bash
export HOME=/home/kristoffer
/usr/local/bin/abbyyocr9 -rl Swedish -if ???fromvalue??? -of ???tovalue??? 2>&1
But I don't know how to get the -from and -to values. Any ideas on how to do it?
The arguments that you provide to a bashscript will appear in the variables $1 and $2 and $3 where the number refers to the argument. $0 is the command itself.
The arguments are seperated by spaces, so if you would provide the -from and -to in the command, they will end up in these variables too, so for this:
./ocrscript.sh -from /home/kristoffer/test.png -to /home/kristoffer/test.txt
You'll get:
$0 # ocrscript.sh
$1 # -from
$2 # /home/kristoffer/test.png
$3 # -to
$4 # /home/kristoffer/test.txt
It might be easier to omit the -from and the -to, like:
ocrscript.sh /home/kristoffer/test.png /home/kristoffer/test.txt
Then you'll have:
$1 # /home/kristoffer/test.png
$2 # /home/kristoffer/test.txt
The downside is that you'll have to supply it in the right order. There are libraries that can make it easier to parse named arguments on the command line, but usually for simple shell scripts you should just use the easy way, if it's no problem.
Then you can do:
/usr/local/bin/abbyyocr9 -rl Swedish -if "$1" -of "$2" 2>&1
The double quotes around the $1 and the $2 are not always necessary but are adviced, because some strings won't work if you don't put them between double quotes.
If you're not completely attached to using "from" and "to" as your option names, it's fairly easy to implement this using getopts:
while getopts f:t: opts; do
case ${opts} in
f) FROM_VAL=${OPTARG} ;;
t) TO_VAL=${OPTARG} ;;
esac
done
getopts is a program that processes command line arguments and conveniently parses them for you.
f:t: specifies that you're expecting 2 parameters that contain values (indicated by the colon). Something like f:t:v says that -v will only be interpreted as a flag.
opts is where the current parameter is stored. The case statement is where you will process this.
${OPTARG} contains the value following the parameter. ${FROM_VAL} for example will get the value /home/kristoffer/test.png if you ran your script like:
ocrscript.sh -f /home/kristoffer/test.png -t /home/kristoffer/test.txt
As the others are suggesting, if this is your first time writing bash scripts you should really read up on some basics. This was just a quick tutorial on how getopts works.
Use the variables "$1", "$2", "$3" and so on to access arguments. To access all of them you can use "$#", or to get the count of arguments $# (might be useful to check for too few or too many arguments).
I needed to make sure that my scripts are entirely portable between various machines, shells and even cygwin versions. Further, my colleagues who were the ones I had to write the scripts for, are programmers, so I ended up using this:
for ((i=1;i<=$#;i++));
do
if [ ${!i} = "-s" ]
then ((i++))
var1=${!i};
elif [ ${!i} = "-log" ];
then ((i++))
logFile=${!i};
elif [ ${!i} = "-x" ];
then ((i++))
var2=${!i};
elif [ ${!i} = "-p" ];
then ((i++))
var3=${!i};
elif [ ${!i} = "-b" ];
then ((i++))
var4=${!i};
elif [ ${!i} = "-l" ];
then ((i++))
var5=${!i};
elif [ ${!i} = "-a" ];
then ((i++))
var6=${!i};
fi
done;
Rationale: I included a launcher.sh script as well, since the whole operation had several steps which were quasi independent on each other (I'm saying "quasi", because even though each script could be run on its own, they were usually all run together), and in two days I found out, that about half of my colleagues, being programmers and all, were too good to be using the launcher file, follow the "usage", or read the HELP which was displayed every time they did something wrong and they were making a mess of the whole thing, running scripts with arguments in the wrong order and complaining that the scripts didn't work properly. Being the choleric I am I decided to overhaul all my scripts to make sure that they are colleague-proof. The code segment above was the first thing.
In bash $1 is the first argument passed to the script, $2 second and so on
/usr/local/bin/abbyyocr9 -rl Swedish -if "$1" -of "$2" 2>&1
So you can use:
./your_script.sh some_source_file.png destination_file.txt
Explanation on double quotes;
consider three scripts:
# foo.sh
bash bar.sh $1
# cat foo2.sh
bash bar.sh "$1"
# bar.sh
echo "1-$1" "2-$2"
Now invoke:
$ bash foo.sh "a b"
1-a 2-b
$ bash foo2.sh "a b"
1-a b 2-
When you invoke foo.sh "a b" then it invokes bar.sh a b (two arguments), and with foo2.sh "a b" it invokes bar.sh "a b" (1 argument). Always have in mind how parameters are passed and expaned in bash, it will save you a lot of headache.

Bash script function call error

I am writing my first Bash script and am running into a syntax issue with a function call.
Specifically, I want to invoke my script like so:
sh myscript.sh -d=<abc>
Where <abc> is the name of a specific directory inside of a fixed parent directory (~/app/dropzone). If the child <abc> directory doesn't exist, I want the script to create it before going to that directory. If the user doesn't invoke the script with a -d argument at all, I want the script to exist with a simple usage message. Here's my best attempt at the script so far:
#!/bin/bash
dropzone="~/app/dropzone"
# If the directory the script user specified exists, overwrite dropzone value with full path
# to directory. If the directory doesn't exist, first create it. If user failed to specify
# -d=<someDirName>, exit the script with a usage statement.
validate_args() {
args=$(getopt d: "$*")
set -- $args
dir=$2
if [ "$dir" ]
then
if [ ! -d "${dropzone}/targets/$dir" ]
then
mkdir ${dropzone}/targets/$dir
fi
dropzone=${dropzone}/targets/$dir
else
usage
fi
}
usage() {
echo "Usage: $0" >&2
exit 1
}
# Validate script arguments.
validate_args $1
# Go to the dropzone directory.
cd dropzone
echo "Arrived at dropzone $dropzone."
# The script will now do other stuff, now that we're in the "dropzone".
# ...etc.
When I try running this I get the following error:
myUser#myMachine:~/app/scripts$ sh myscript.sh -dyoyo
mkdir: cannot create directory `/home/myUser/app/dropzone/targets/yoyo': No such file or directory
myscript.sh: 33: cd: can't cd to dropzone
Arrived at dropzone /home/myUser/app/dropzone/targets/yoyo.
Where am I going wrong, and is my general approach even correct? Thanks in advance!
Move the function definitions to the top of the script (below the hash-bang). bash is objecting to the undefined (at that point) call to validate_args. usage definition should precede the definition of validate_args.
There also should be spacing in the if tests "[ " and " ]".
if [ -d "$dropzone/targets/$1" ]
The getopt test for option d should be-:
if [ "$(getopt d "$1")" ]
Here is a version of validate_args that works for me.
I also had to change the drop zone as on my shell ~ wouldn't expand in mkdir command.
dropzone="/home/suspectus/app/dropzone"
validate_args() {
args=$(getopt d: "$*")
set -- $args
dir=$2
if [ "$dir" ]
then
if [ ! -d "${dropzone}/targets/$dir" ]
then
mkdir ${dropzone}/targets/$dir
fi
dropzone=${dropzone}/targets/$dir
else
usage
fi
}
To pass in all args use $* as parameter -:
validate_args $*
And finally call the script like this for getopt to parse correctly-:
myscript.sh -d dir_name
When invoked, a function is indistinguishable from a command — so you don't use parentheses:
validate_args($1) # Wrong
validate_args $1 # Right
Additionally, as suspectus points out in his answer, functions must be defined before they are invoked. You can see this with the script:
usage
usage()
{
echo "Usage: $0" >&2
exit 1
}
which will report usage: command not found assuming you don't have a command or function called usage available. Place the invocation after the function definition and it will work fine.
Your chosen interface is not the standard Unix calling convention for commands. You'd normally use:
dropzone -d subdir
rather than
dropzone -d=subdir
However, we can handle your chosen interface (but not using getopts, the built-in command interpreter, and maybe not using GNU getopt either, and certainly not using getopt as you tried to do so). Here's workable code supporting -d=subdir:
#!/bin/bash
dropzone="$HOME/app/dropzone/targets"
validate_args()
{
case "$1" in
(-d=*) dropzone="$dropzone/${1#-d=}"; mkdir -p $dropzone;;
(*) usage;;
esac
}
usage()
{
echo "Usage: $0 -d=dropzone" >&2
exit 1
}
# Validate script arguments.
validate_args $1
# Go to the dropzone directory.
cd $dropzone || exit 1
echo "Arrived at dropzone $dropzone."
# The script will now do other stuff, now that we're in the "dropzone".
# ...etc.
Note the cautious approach with the cd $dropzone || exit 1; if the cd fails, you definitely do not want to continue in the wrong directory.
Using the getopts built-in command interpreter:
#!/bin/bash
dropzone="$HOME/app/dropzone/targets"
usage()
{
echo "Usage: $0 -d dropzone" >&2
exit 1
}
while getopts d: opt
do
case "$opt" in
(d) dropzone="$dropzone/$OPTARG"; mkdir -p $dropzone;;
(*) usage;;
esac
done
shift $(($OPTIND - 1))
# Go to the dropzone directory.
cd $dropzone || exit 1
echo "Arrived at dropzone $dropzone."
# The script will now do other stuff, now that we're in the "dropzone".
# ...etc.

Resources