linux shell script variable "not found" - linux

Just trying to exit a loop once no input is entered at the prompt, but I'm having trouble testing for the value in an if statement?
CODE:
SQL="?";
while true
do
if [ "$SQL" == "" ]
then
break
else
read -p "SQL: " SQL
clear
php -f sql.php "$SQL"
fi
done
OUTPUT:
sql.sh: 5: [: ?: unexpected operator
SQL:

Although it looks like part of a scripting language, [ is actually the name of a command, also known as test. The if statement runs that command, and acts based on its result. (The same is true, incidentally, of the true in your while loop - it's a command that "does nothing, successfully".)
As such, you need a space between the command and its parameters, as well as between the if and the command. You also need to use the correct arguments; the standard spelling for comparing two strings is = rather than ==
if [ "$SQL" = "" ]
Which is equivalent to:
if test "$SQL" = ""

Related

Assigning variable to a variable inside if statement

I am trying to assign a variable from a prompt input choice with no luck. If the user inputs 1, I want target_db_name = "database2".
My code:
while true; do
read -p "What is the table name?" table_name
table_name=${table_name,,}
if hdfs dfs -test -e /foo/$table_name ;
then read -p "What is the target database you want to copy the
“foo.${table_name}” table to?
Your three options are:
1) database1
2) database2
3) database3
Type 1, 2, or 3: " target_db;
(((Here is where I want to state if $target_db = "1" then target_db_name
= "database1", if $target_db = "2" then target_db_name = "database2" etc...)))
read -p "Would you like to begin the HDFS copy with the following configuration:
Target Database: ${target_db_name}
Table Name: ${table_name}
Continue (Y/N):"
else echo "Please provide a valid table name.
Exiting this script" ; exit ; fi
done
I have tried creating another if statement with no luck.
"....Type 1, 2, or 3: " target_db;
else if $target_db = "1" then target_db_name = "edw_qa_history"; fi
if $target_db = "1" then won't work, because what follows if must be a command, not a test expression. Now, the most common command used in if statements is [ (yes, that's actually a command name; it's synonymous with the test command), which takes a test expression (and a close bracket) as its arguments and succeeds or fails depending on whether the expression is true or not. So the correct syntax would be something like:
if [ "$target_db" = "1" ]; then
Note that there are two other differences from what you had: I put double-quotes around the variable reference (almost always a good idea, to avoid may parsing oddities), and added a semicolon before then (needed to indicate where the arguments to [ end and shell syntax resumes). I also notice you have semicolons at the end of many lines of your script; this isn't necessary, the end-of-line is enough to indicate the end of a command. It's only if you have another command (or something like then) on the same line that you need a semicolon as a delimiter.
HOWEVER, as #Barmar pointed out in a comment, case would probably be better than a list of if and elif statements here. case is intended specifically for comparing a string against a list of other strings (or patterns), and executing different things depending on which one it matches. It looks something like this:
case "$target_db" in
1) target_db_name="database1" ;;
2) target_db_name="database2" ;;
3) target_db_name="database3" ;;
*) "Please provide a valid table name. Exiting this script" ; exit ;;
esac
Here, the double-semicolon is needed, even at the end of a line, to indicate the end of each case. Also, note that the * pattern (the last case) matches anything, so it functions like an else would in an if ... elif ... sequence.
Final note: use shellcheck.net to sanity-check your code.
You don't need an if statement to map the number to an array; you just need an array.
db_names=(
"datebase 1"
"database 2"
"database 3"
)
# ...
target_db_name=${db_names[$target_db - 1]}
if [[ -z $target_db_name ]]; then
exit
fi

Having trouble with simple Bash if/elif/else statement

I'm writing bash scripts that need to work both on Linux and on Mac.
I'm writing a function that will return a directory path depending on which environment I'm in.
Here is the pseudo code:
If I'm on a Mac OS X machine, I need my function to return the path:
/usr/local/share/
Else if I'm on a Linux machine, I need my function to return the path:
/home/share/
Else, you are neither on a Linux or a Mac...sorry.
I'm very new to Bash, so I apologize in advance for the really simple question.
Below is the function I have written. Whether I'm on a Mac or Linux, it always returns
/usr/local/share/
Please take a look and enlighten me with the subtleties of Bash.
function get_path(){
os_type=`uname`
if [ $os_type=="Darwin" ]; then
path="/usr/local/share/"
elif [ $os_type=="Linux" ]; then
path="/home/share/"
else
echo "${os_type} is not supported"
exit 1
fi
echo $path
}
You need spaces around the operator in a test command: [ $os_type == "Darwin" ] instead of [ $os_type=="Darwin" ]. Actually, you should also use = instead of == (the double-equal is a bashism, and will not work in all shells). Also, the function keyword is also nonstandard, you should leave it off. Also, you should double-quote variable references (like "$os_type") just in case they contain spaces or any other funny characters. Finally, echoing an error message ("...not supported") to standard output may confuse whatever's calling the function, because it'll appear where it expected to find a path; redirect it to standard error (>&2) instead. Here's what I get with these cleaned up:
get_path(){
os_type=`uname`
if [ "$os_type" = "Darwin" ]; then
path="/usr/local/share/"
elif [ "$os_type" = "Linux" ]; then
path="/home/share/"
else
echo "${os_type} is not supported" >&2
exit 1
fi
echo "$path"
}
EDIT: My explanation of the difference between assignments and comparisons got too long for a comment, so I'm adding it here. In many languages, there's a standard expression syntax that'll be the same when it's used independently vs. in test. For example, in C a = b does the same thing whether it's alone on a line, or in a context like if ( a = b ). The shell isn't like that -- its syntax and semantics vary wildly depending on the exact context, and it's the context (not the number of equal signs) that determines the meaning. Here are some examples:
a=b by itself is an assignment
a = b by itself will run a as a command, and pass it the arguments "=" and "b".
[ a = b ] runs the [ command (which is a synonym for the test command) with the arguments "a", "=", "b", and "]" -- it ignores the "]", and parses the others as a comparison expression.
[ a=b ] also runs the [ (test) command, but this time after removing the "]" it only sees a single argument, "a=b" -- and when test is given a single argument it returns true if the argument isn't blank, which this one isn't.
bash's builtin version of [ (test) accepts == as a synonym for =, but not all other versions do.
BTW, just to make things more complicated bash also has [[ ]] expressions (like test, but cleaner and more powerful) and (( )) expressions (which are totally different from everything else), and even ( ) (which runs its contents as a command, but in a subshell).
You need to understand what [ means. Originally, this was a synonym for the /bin/test command. These are identical:
if test -z "$foo"
then
echo "String '$foo' is null."
fi
if [ -z "$foo" ]
then
echo "String '$foo' is null."
fi
Now, you can see why spaces are needed for all of the parameters. These are parameters and not merely boolean expressions. In fact, the test manpage is a great place to learn about the various tests. (Note: The test and [ are built in commands to the BASH shell.)
if [ $os_type=="Darwin" ]
then
This should be three parameters:
"$os_type"
= and not ==
"Darwin"
if [ "$os_type" = "Darwin" ] # Three parameters to the [ command
then
If you use single square brackets, you should be in the habit to surround your parameters with quotation marks. Otherwise, you will run into trouble:
foo="The value of FOO"
bar="The value of BAR"
if [ $foo != $bar ] #This won't work
then
...
In the above, the shell will interpolate $foo and $bar with their values before evaluating the expressions. You'll get:
if [ The value of FOO != The value of BAR ]
The [ will look at this and realize that neither The or value are correct parameters, and will complain. Using quotes will prevent this:
if [ "$foo" != "$bar" ] #This will work
then
This becomes:
if [ "The value of FOO" != "The value of BAR" ]
This is why it's highly recommended that you use double square brackets for your tests: [[ ... ]]. The test looks at the parameters before the shell interpolates them:
if [[ $foo = $bar ]] #This will work even without quotation marks
Also, the [[ ... ]] allows for pattern matching:
if [[ $os_type = D* ]] # Single equals is supported
then
path="/usr/local/share/"
elif [[ $os_type == L* ]] # Double equals is also supported
then
path="/home/share/"
else
echo "${os_type} is not supported"
exit 1
fi
This way, if the string is Darwin32 or Darwin64, the if statement still functions. Again, notice that there has to be white spaces around everything because these are parameters to a command (actually, not anymore, but that's the way the shell parses them).
Adding spaces between the arguments for the conditionals fixed the problem.
This works
function get_path(){
os_type=`uname`
if [ $os_type == "Darwin" ]; then
path="/usr/local/share/"
elif [ $os_type == "Linux" ]; then
path="/home/share/"
else
echo "${os_type} is not supported"
exit 1
fi
echo $path
}

Conditional statement not working as expected

I am using Konsole on kubuntu 14.04.
I want to take arguments to this shell-script, and pass it to a command. The code is basically an infinite loop, and I want one of the arguments to the inner command to be increased once every 3 iterations of the loop. Ignoring the actual details, here's a gist of my code:
#!/bin/bash
ct=0
begin=$1
while :
do
echo "give: $begin as argument to the command"
#actual command
ct=$((ct+1))
if [ $ct%3==0 ]; then
begin=$(($begin+1))
fi
done
I am expecting the begin variable to be increased every 3 iterations, but it is increasing in the every iteration of the loop. What am I doing wrong?
You want to test with
if [ $(expr $cr % 3) = 0 ]; then ...
because this
[ $ct%3==0 ]
tests whether the string $ct%3==0, after parameter substitution, is not empty. A good way for understanding this is reading the manual for test and look at the semantics when it is given 1, 2, 3 or more arguments. In your original script, it only sees one argument, in mine it sees three. White space is very important in the shell. :-)
In BASH you can completely utilize ((...)) and refactor your script like this:
#!/bin/bash
ct=0
begin="$1"
while :
do
echo "give: $begin as argument to the command"
#actual command
(( ct++ % 3 == 0)) && (( begin++ ))
done

undefined variable error in csh script

I have one function in csh script and in this function I am using one variable which is sourced from one file. But while using script its throwing undefined error for same variable.
I am using Linux.
My Code
function init_remote_commands_to_use
{
# Test if the environment variable SSH_FOR_RCOMMANDS is present in .temip_config file,
# use secured on non secured rcommand depending on the result
if [ "$SSH_FOR_RCOMMANDS" != "" ]
then
if [ "$SSH_FOR_RCOMMANDS" = "ON" ]
then
# Check if the environment variable SSH_PATH is specified in .temip_config file
if [ "$SSH_PATH" != "" ]
then
SH_RCMD=$SSH_PATH
else
SH_RCMD=$SSH_CMD
fi
# Check if a ssh-agent is already running
if [ "$SSH_AGENT_PID" = "" ]
then
#Run ssh-agent for secured RCommands
eval `ssh-agent`
ssh-add
STARTEDBYME=YES
fi
else
if [ "$SSH_FOR_RCOMMANDS" = "OFF" ]
then
SH_RCMD=$RSH_CMD
else
echo "Please set the SSH_FOR_RCOMMANDS value to ON or OFF in the .temip_config file"
exit 1
fi
fi
else
SH_RCMD=$RSH_CMD
fi
}
below is the error:
function: Command not found.
{: Command not found.
SSH_FOR_RCOMMANDS: Undefined variable.
Please anyone suggest what I am missing?
The C Shell csh does not have functions. It does have aliases, but those are harder to write and read. For exmaple, see here: https://unix.stackexchange.com/questions/62032/error-converting-a-bash-function-to-a-csh-alias
It might be a good idea to simply switch to Bash, where your existing code may already be working.

Error when trying to compare strings in shell script

I have the following in my script:
fw=$2
if [ "$fw" == "zf" ]
then
public_dir=$dir/current/public
else
public_dir=$dir/current
fi
But I get the following error when I run it:
./generatevhost.sh: 15: [: zf: unexpected operator
I've lookup pages explaining how to compare strings and they describe like so. What am I doing wrong?
I believe you're not using BASH or ksh. Try this if condition by replacing == by =:
fw="$2"
if [ "$fw" = "zf" ]
then
public_dir=$dir/current/public
else
public_dir=$dir/current
fi

Resources