How to convert shell script variable from string to an integer - bash

My script has a line that measures the number of instances of a process being run
procs=$(pgrep -f luminati | wc -l);
However, even though the content of $procs is a numeral, the shell script is not storing $procs as an integer. It is being stored as a string.
Therefore I cannot run conditionals like
if $procs > 3
Is there any way to convert this variable to integer type?

In bash > is truncate which writes to a file. You probably have a file called 3 now. You should use the comparitor -gt:
if [[ "$procs" -gt 3 ]]; then
...
fi
Also, you don't have separate types for integers and strings.
Edit:
As #chepner explained, for POSIX compatibility you should use single brackets:
if [ "$procs" -gt 3 ];

Should be
if [[ "$procs" -gt 3 ]]
then
...
fi

Related

Getting the line count of a file in a shell script with wc failing

my script check if the arguments are files or folders
if it is a file, he count the number of lines
after that, if the number of lines is great then 20 or less he do some instructions
the problem is in this instructionn= cat $a | wc -l
My script:
#!/usr/bin/env bash
echo 'Hello this is the test of' `date`
echo 'arguments number is ' $#
if [ $# -eq 4 ]
then
for a in $#
do
if [ -d $a ]
then
ls $a > /tmp/contenu
echo "contenu modified"
elif [ -f $a ]
then
# this instruction must set a numeric value into n
echo "my bad instruction"
n= cat $a | wc -l
echo "number of lines = " $n
# using the numeric value in a test (n must be numeric and takes the number of lines in the current file)
if [ $n -eq 0 ]
then
echo "empty file"
elif [ $n -gt 20 ]
then
echo ` head -n 10 $a `
else
cat $a
fi
else
echo "no file or directory found"
fi
done
else
echo "args number must be 4"
fi
This is the output of the execution of the incorrect instruction
my bad instruction
5
number of lines =
ExamenEx2.sh: line 19: [: -eq : opérateur unaire attendu
The line n= cat $a | wc -l is an offending instruction. Always remember that bash shell scripting is extremely case-sensitive. Your command is interpreted by the shell as having to run two separate commands
n= cat $a | wc -l
#^^ ^^^^^^^^^^^^^^
#1 2
The first part just stores an empty string to the variable n and the next prints the line count of the file stored in variable a. Notice that the shell does not throw errors for this. Because it is not violating the syntax (just the semantics are wrong). But the line count is never assigned to the variable n.
The error is seen when the conditional if [ $n -eq 0 ] is hit when you are doing a comparison with an empty variable on the LHS.
You wanted to run a command and store its output, you need command-substitution($(..)) for that. Assuming the $a contains a name of a file just do
n=$(wc -l < "$a")
Note, that I've removed the useless cat usage and piping it to wc. But wc can read from an input stream directly.
Also note that you have multiple bad practices in your script. Remember to do the following
Always double-quote the shell variables - "$#", "$#", [ -f "$a" ], [ -d "$a" ]
Don't use the `` for command-substitution, because it is not easily nestable and you might have issues related to quoting also.
You can use conditional expression [[ if you are sure if the script is running under bash in which a variable containing spaces can be used without quoting on the LHS

Multiple If Statements in Bash Script

I am trying to make a bash script with the output based on the input.
My code looks like this:
#!/bin/bash
echo "Letter:"
read a
if a=3
then
echo "LOL"
fi
if a=4
then
echo "ROFL"
fi
But when I enter 3 or 4, I get both LOL and ROFL.
Is there a way for me to get LOL for 3 and ROFL for 4?
Sorry if I'm using incorrect terms and stuff, I'm new to bash scripting.
In bash, a=3 is an assignment, not a test. Use, e.g.:
if [ "$a" = 3 ]
Inside [...], the equal sign tests for string (character) equality. If you want to test for numeric value instead, then use '-eq` as in:
if [ "$a" -eq 3 ]
The quotes around "$a" above are necessary to avoid an "operator" error when a is empty.
bash also offers a conditional expressions that begin with [[ and have a different format. Many like the [[ format better (it avoids, for example, the quote issue mentioned above) but the cost is loss of compatibility with other shells. In particular, note that dash, which is the default shell (/bin/sh) for scripts under Debian-derived distributions, does not have [[.
Bash thinks you're trying to assign a variable by saying a=3. You can do the following to fix this:
Use the = operator whilst referencing the variable with a $, like so: if [[ $a = 3 ]]
Use the -eq operator, which is special and doesn't require you to reference the variable with a $, but may not be compatible with all sh-derived shells: if [[ a -eq 3 ]]. If you wish to use -eq without Bash reference the variable: if [[ $a -eq 3 ]]
Note:
The double square brackets [[ ... ]] are a preferred format with specifically Bash conditionals. [ ... ] is good with any sh-derived shell (zsh, tcsh, etc).
if a=3 will assign value 3 to variable a
unless a is readonly variable, if a=3 always returns TRUE
same for if a=4
To compare variable a with a value, you can do this if [ $a = 3 ]
so the script should change to
#!/bin/bash
echo "Letter:"
read a
if [ $a = 3 ]
then
echo "LOL"
fi
if [ $a = 4 ]
then
echo "ROFL"
fi
Since a is read from user input, there is possibility user key in:
non numeric value
a string with empty space
nothing, user may just press Enter key
so a safer way to check is:
if [ "x$a" = "x3" ]

solaris simple bash script

I'm trying to execute this simple script in solaris.
I want to sort(numeric) the filenames of the files in source directory and copy the file one by one to another directory. And, I want to print a message after copying every 100 files.
#!/bin/bash
count=0
for i in `ls | sort -n`
do
cp $i ../target
count = $((count+1))
if[ $count%100 -eq 0 ]
then
echo $count files copied
sleep 1
fi
done
this is not working. I tried different things after searching in net.
I get errors like these -
syntax error at line 8: '(' unexpected.
syntax error at line 10: 'then' unexpected.
syntax error at line 13: 'fi' unexpected etc.
What is the problem with this script?
bash version - GNU bash, version 3.00.16(1)-release (sparc-sun-solaris2.10)
The basic problem with the script is spacing. You have spaces where you shouldn't have them:
(wrong) count = $((count+1))
(right) count=$((count+1))
(better) ((count++))
and you're missing spaces where you need them:
(wrong) if[ $count%100 -eq 0 ]
(right) if [ $((count % 100)) -eq 0 ]
(better) if ((count % 100 == 0))
count = $((count+1)) tries to run the command count passing it two arguments, = and the value of count+1. if[ ... tries to run the command if[ because [ is a valid word character; it doesn't automatically start a new token.
Having said all that, I'm puzzled by the unexpected ( error message. Could your bash be too old to recognize $(( syntax? Possibly. It's a very old bash.
count=$((count+1))
if [ `echo $count % 100 | bc` -eq 0 ]
Make these corrections.
Edit: Please try
count=`expr $count + 1`
I see a few errors here. First, you need double quotes around $i in case they have special characters.
Second, you shouldn't ever use
for i in `ls | sort -n`
Instead, try the following
ls -1 | sort -n | while read i
Third, change your if statement to
if ((count%5 == 0))
The (( syntax is bash is made just for integer math.
Fourth, change your counter increment to
((count++))
This is more concise. Also, the space in your version may break things. Remember, spaces matter.

Why does my script report ls: not found

I have the following korn script:
#!/bin/ksh
TAPPDATADIR=/hp/qa02/App/IPHSLDI/Data
echo $TAPPDATADIR
if [[ls $TAPPDATADIR/zip_file_MD5_checksum*.txt | wc -l > 1]]
then
exit "asdf"
fi
When I attempt to run it I get:
/hp/qa02/App/IPHSLDI/Data
./iftest.ksh: line 7: [[ls: not found
Why isn't my if statement working?
I'm trying to see if there are multiple checksum files in the Data directory. If there are I want to exit the script.
There are several problems:
There shouldn't be any spaces around = in the assignment.
You need spaces around [[ and ]] in the if statement.
To substitute the result of a command into the test expression, you need to use backticks or $(...).
The parameter to exit should be a number, I think you just want to echo the string.
> performs string comparison, you have to use -gt to perform numeric comparison.
So the full script should be:
#!/bin/ksh
TAPPDATADIR=/hp/qa02/App/IPHSLDI/Data
echo $TAPPDATADIR
if [[ $(ls $TAPPDATADIR/zip_file_MD5_checksum*.txt | wc -l) -gt 1 ]]
then
echo "asdf"
fi

test command in KornShell (ksh)

I have a question on the test command in the KornShell (ksh). I know -ne is for comparing integers and != is for comparing strings. How will the test command behave if one argument is a string and the other is an integer? I have below conditions in my code and both are working properly.
Code:
myCount=1
myCount=`expr $myCount+ 0`
temp=`ps -aef | grep damn | wc -l`
if [ $temp -ne $myCount]; then
echo ERROR Number
fi
if [ $temp != $myCount ]; then
echo ERROR Strings
fi
Output:
ERROR Number
ERROR Strings
The type is not relevant because it's a simple text substitution. In other words, the value of the variable $temp will be substituted in place of $temp (for example).
At least for the version of ksh I'm running, for the numeric comparison, if the value starts with a non-numeric, it will equate to 0. If it starts with a numeric but contains non-numerics, you will get an error.
For example:
$ export s1=xyz
$ export s2=7xyz
$ export i1=0
$ if [ $i1 -eq $s1 ]
> then
> echo equal
> fi
equal
$ if [ $i1 -eq $s2 ]
> then
> echo equal
> fi
ksh: 7xyz: bad number `7xyz'
However, based on your comments, that may not be the case for all versions of ksh.
Based on that, I would try to ensure that you use string comparisons for strings and numeric comparisons for numbers. Anything else may be non-portable.
But your code is flawed anyway.
temp=ps -aef | grep damn | wc -l
will always return at least 1, since it will find the grep command as well as being a string padded with leading spaces, which is why both of your tests are true.
Piping to wc is also unnecessary since the -c switch of grep will count for you.
better code would be:
temp=ps -aef |grep damn |grep -cv grep
which will return the number of running instances of processes containing the damn string and it will be a number.
Using ksh93 and GNU coreutils expr 7.4 your command:
myCount=`expr $myCount+ 0`
gives me a syntax error and sets myCount to null which causes both if statements to output "ksh: [: argument expected" errors. Try putting a space before the plus sign. Also, there needs to be a space before ].
You shouldn't need to convert myCount or temp to integers. The coercion of myCount using expr is completely unnecessary.
I prefer this form for comparing integers since it allows you to use symbolic comparison operators such as != and > instead of -ne and -gt:
if (( $temp != $myCount ))

Resources