Unix : Integer expression expected - bash

#!/bin/bash
location=$1
englishCount=0
bourneCount=0
CShellCount=0
symbolicCount=0
emptyCount=0
dirCount=0
if [ ! $# -eq 1 ]; then
echo Need to supply one argument
exit
fi
if [ ! -d $1 ]; then
echo Directory not found
exit
fi
find $location | while read item
do
if [-f "$item" ]
then
if [ "file $loc/* | grep English | wc -l" -eq 1 ]
then
$englishCount=$[englishCount+1]
elif [ "file $loc/* | grep Bourne | wc -l" -eq 1 ]
then
$bourneCount=$[bourneCount+1]
elif [ "file $loc/* | grep C.Shell | wc -l" -eq 1 ]
then
$CShellCount=$[$CShellCount+1]
elif [ "file $loc/* | grep symbolic | wc -l" -eq 1 ]
then
$symbolicCount=$[$symbolicCount+1 ]
elif
$emptyCount=$[$emptyCount+1 ]
elif [ -d "$item" ]
then
dirCount=$[dirCount+1]
fi
done
echo "English count: " $englishCount
echo "bourne count: " $bourneCount
echo "CShell count: " $CShellCount
echo "symbolic count : " $symbolicCount
echo "empty count: " $emptyCount
echo "Directory count: " $dirCount
I'm trying to create a script to sort the contents of a directory by type but, I get an error saying that Integer expression expected. IM under the impression that the expression used to compare to the integer one would result in a numeric value but, my script does not recognize it as such.

In the line
if [ "file $loc/* | grep English | wc -l" -eq 1 ]
You are comparing a string with a number. Instead try
if [ `file $loc/* | grep English | wc -l` -eq 1 ]
The back ticks cause "the thing between them" to be run as a subprocess, with the result returned to this program. And then the "string" that is returned (some numeric output from wc -l ) is turned into an integer and compared with 1.
Obviously you have do to this to all similar instances.

Related

Problem with Grep in if statement doesn't work in bash rnot returning 0

I have a bash script and I want to check with an (el) if statement if a string is not in a file and then run an action
This is the part of the script:
elif [ "$(cat balance.txt)" -eq 250000000 ] && [ "$(find files/ -type f | wc -l)" -ge 5 ] && [ "$(grep -c "$(cat string.txt)" whitelist.txt)" -ge 1 ] && [ "$(grep -c "$(cat string.txt)" whitelist2.txt) " -eq 0 ] ;
then
sh result.sh
The first 2 parts of the elif statements are working but only the third part gives me problems:
[ "$(grep -c "$(cat string.txt)" whitelist2.txt) " -eq 0 ]
It skips this part and goes straight to the else part of the script which runs fine.
Does anybody maybe knows what I am doing wrong? Or what is should change?

How to apply cut and sed commands to Powershell?

I have a bash script which retrieves data from 2 separate files (1 for user data and another for default text) and outputs a circular letter:
if [ $# -eq 0 ]
then
echo "Please enter two parameters"
exit
elif [ $# -eq 1 ]
then
echo "Please enter one more parameter"
exit
elif [ $# -gt 2 ]
then
echo "Please enter ONLY two parameters"
exit
fi
while read line
do
iN=`echo $line | cut -f1 -d";"`
iA=`echo $line | cut -f2 -d";"`
iD=`echo $line | cut -f3 -d";"`
cat $2|sed "s/<NAME>/$iN/g" | sed "s/<ADDRESS>/iA/g" | sed "s/<DATE>/$iD/g"
done < data
It needs to be converted to a PS script, here's what I could've done so far:
if ($# -eq 0) {
Write-Output "Please enter two parameters"
} elseif ($# -eq 1 ) {
Write-Output "Please enter one more parameter"
} elseif ($# -gt 2) {
Write-Output "Please enter ONLY two parameters"
}
foreach($line in Get-Content .\data.txt) {
}
I wasn't able to find any equivalent of sed or cut commands on the internet so I'd appreciate any kind of help.
You can use Unix Utils for Windows set that has all these commands converted, and we have been using them for a long time in production with no issues.
https://sourceforge.net/projects/unxutils/
It has most of them: sed, cut, cat etc.

nested logical expression test in shell

I am trying to write a one-liner as a replacement for the below snippet.
# Check to see if the database is online; exit if not
isbooted=`grep 'Current state: Booted' serverlog.log | wc -l`
if [ $isbooted -eq 0 ]
then
exit
fi
# Check to see if the database has crashed; exit if so
iscrashed=`grep 'Status: OK' serverlog.log | wc -l`
if [ $iscrashed -eq 0 ]
then
exit
fi
echo 0
This is what I have done so far (I am unsure if this is correct),
[ $(grep 'Current state: Booted' serverlog.log | wc -l) -eq 0 ] \
&& [ $(grep 'Status: OK' serverlog.log | wc -l) -eq 0 ] \
&& echo 0
Can you please help me here?
The idea seems ok, but I'd go with a simplified version:
grep -q 'Current state: Booted' serverlog.log && grep -q 'Status: OK' serverlog.log && echo 0
or alternatively (you can replace -ge with -eq if you expect both lines to occur exactly once):
[ "$(grep -c -e 'Current state: Booted' -e 'Status: OK' serverlog.log)" -ge 2 ] && echo 0
Both versions print 0 if serverlog.log contains both 'Current state: Booted' and Status: OK.
For further reference see grep(1).

Check if program is running with bash shell script?

This is an example of a bash script which checks for some running process (daemon or service) and does specific actions (reload, sends mail) if there is no such process running.
check_process(){
# check the args
if [ "$1" = "" ];
then
return 0
fi
#PROCESS_NUM => get the process number regarding the given thread name
PROCESS_NUM='ps -ef | grep "$1" | grep -v "grep" | wc -l'
# for degbuging...
$PROCESS_NUM
if [ $PROCESS_NUM -eq 1 ];
then
return 1
else
return 0
fi
}
# Check whether the instance of thread exists:
while [ 1 ] ; do
echo 'begin checking...'
check_process "python test_demo.py" # the thread name
CHECK_RET = $?
if [ $CHECK_RET -eq 0 ]; # none exist
then
# do something...
fi
sleep 60
done
However, it doesn't work. I got "ERROR: Garbage option." for the ps command. What's wrong with these scripts? Thanks!
You can achieve almost everything in PROCESS_NUM with this one-liner:
[ `pgrep $1` ] && return 1 || return 0
if you're looking for a partial match, i.e. program is named foobar and you want your $1 to be just foo you can add the -f switch to pgrep:
[[ `pgrep -f $1` ]] && return 1 || return 0
Putting it all together your script could be reworked like this:
#!/bin/bash
check_process() {
echo "$ts: checking $1"
[ "$1" = "" ] && return 0
[ `pgrep -n $1` ] && return 1 || return 0
}
while [ 1 ]; do
# timestamp
ts=`date +%T`
echo "$ts: begin checking..."
check_process "dropbox"
[ $? -eq 0 ] && echo "$ts: not running, restarting..." && `dropbox start -i > /dev/null`
sleep 5
done
Running it would look like this:
# SHELL #1
22:07:26: begin checking...
22:07:26: checking dropbox
22:07:31: begin checking...
22:07:31: checking dropbox
# SHELL #2
$ dropbox stop
Dropbox daemon stopped.
# SHELL #1
22:07:36: begin checking...
22:07:36: checking dropbox
22:07:36: not running, restarting...
22:07:42: begin checking...
22:07:42: checking dropbox
Hope this helps!
If you want to execute that command, you should probably change:
PROCESS_NUM='ps -ef | grep "$1" | grep -v "grep" | wc -l'
to:
PROCESS_NUM=$(ps -ef | grep "$1" | grep -v "grep" | wc -l)
PROCESS="process name shown in ps -ef"
START_OR_STOP=1 # 0 = start | 1 = stop
MAX=30
COUNT=0
until [ $COUNT -gt $MAX ] ; do
echo -ne "."
PROCESS_NUM=$(ps -ef | grep "$PROCESS" | grep -v `basename $0` | grep -v "grep" | wc -l)
if [ $PROCESS_NUM -gt 0 ]; then
#runs
RET=1
else
#stopped
RET=0
fi
if [ $RET -eq $START_OR_STOP ]; then
sleep 5 #wait...
else
if [ $START_OR_STOP -eq 1 ]; then
echo -ne " stopped"
else
echo -ne " started"
fi
echo
exit 0
fi
let COUNT=COUNT+1
done
if [ $START_OR_STOP -eq 1 ]; then
echo -ne " !!$PROCESS failed to stop!! "
else
echo -ne " !!$PROCESS failed to start!! "
fi
echo
exit 1

Bash split substring

I am receiving numeric variables sometimes with 2, other times with 3 digits, like '321' and '32'. And I want to put a dot among each of the numbers. So if I receive '32', I got to echo '3.2' and if I receive '321' I echo '3.2.1'.
This is what I did:
S='321'
SL="${#S}" #string lentgh
n1=`echo $S | cut -c 1-1`
n2=`echo $S | cut -c 2-2`
if [ "$SL" -eq 2 ]; then
echo $n1.$n2
elif [ "$SL" -eq 3 ]; then
n3=`echo $S | cut -c 3-3`
echo $n1.$n2.$n3
else
die 'Works only with 2 or 3 digits'
fi
My question is: is there any shorter way of doing the same thing?
UPDATE:
Shorter but still verbose:
SL="${#1}" #string lentgh
S=$1
if [ "$1" -eq 3 ]; then
$n3=".${S:2:1}"
fi
if [ "$SL" -lt 2 ] && [ "$SL" -gt 3 ]; then
die 'Works only with 2 or 3 digits'
fi
echo "${S:0:1}.${S:1:1}$n3"
UPDATE 1:
If I include the if block, the sed+regex version will be quite as long as the pure bash version:
SL="${#1}" #string lentgh
S=$1
N=$(echo $S | sed -r "s/([0-9])/\1./g")
echo ${N%%.}
if [ "$SL" -lt 2 ] && [ "$SL" -gt 3 ]; then
die 'Works only with 2 or 3 digits'
fi
Or, using a one line sed+regex with two expressions:
SL="${#1}" #string lentgh
echo $1 | sed -e 's/\([[:digit:]]\)/.\1/g' -e 's/^\.//'
if [ "$SL" -lt 2 ] && [ "$SL" -gt 3 ]; then
die 'Works only with 2 or 3 digits'
fi
Thanks.
I prefer also the sed for that:
echo 321 | sed -e 's/\([[:digit:]]\)/.\1/g' | cut -b2- -> 3.2.1
echo 32 | sed -e 's/\([[:digit:]]\)/.\1/g' | cut -b2- -> 3.2
Or without cut it looks like this
echo 321 | sed -e 's/\([[:digit:]]\)/.\1/g' -e 's/^\.//'
Here is one. This will work for any string length.
#!/bin/bash
#s is the string
#fs is the final string
echo "Enter string"
read s
n="${#s}"
fs=""
i=0
for ((i=0; i<n; i++))
do
fs="$fs.${s:i:1}"
done
#find the length of the final string and
#remove the leading '.'
n="${#fs}"
fs="${fs:1}"
echo "$fs"
It's not that pretty, but at least it's short:
num=$(echo $S | sed -r "s/([0-9])/\1./g")
echo ${num%%.}
S='321'
perl -e "print join '.', split //, shift" "$S"

Resources