bash for with numerical comparison and file existence - bash

I tried to do a for loop with 2 conditions but I didn't succeed in any way:
for (( i=0 ; -e /file && i < 10 ; i++ ))
of course I tried any combination of parentheses like:
for (( i=0 ; [ -e /file ] && [ i < 10 ] ; i++ ))
for (( i=0 ; [ -e /file -a i < 10 ] ; i++ ))
What's wrong on this?
I googled a lot for this, but I didn't find any suggestion.

You have to do some subshell trickery to pull this off:
for (( i=0 ; $([ -e /file -a $i -lt 10 ]; echo "$?") == 0; i++ ))
Or probably better:
for (( i=0 ; $([ -e /file ]; echo "$?") == 0 && i < 10; i++ ))
What's happening here is that $(...) is being run and placed into the mathematical expression ... == 0. When it's run the echo "$?" spits out the return code for [ which is 0 for no-error (i.e. expression is true), and 1 for error (i.e. expression is false) which then gets inserted as 0 == 0 or 1 == 0.

Related

How to say less than but no equal to in bash?

I'm getting an error with this, I did my research but found nothing.
if [ $value -lt 3 -ne 1 ]; then
execute code
fi
line 6: [: syntax error: -ne unexpected
One way to make this work is
if [ "${value}" -lt 3 ] && [ "${value}" -ne 1 ]; then
echo "Hello"
fi
I like to switch to arithmetic expressions using (( when I need tests like these:
declare -a values=(1 2 3)
for value in "${values[#]}"; do
if (( value != 1 && value < 3 )); then
echo "execute code for $value"
fi
done
The above outputs:
execute code for 2
use (( )) brackets for arithmetic operations and [[ ]] for strings comparison
$ is redundant in round brackets so (( $a == 1 )) is the same as (( a == 1 ))
typeset a=2
(( a < 3 )) && (( a != 1 )) && echo "Execute code"
more details : http://faculty.salina.k-state.edu/tim/unix_sg/bash/math.html

Sum digits of a number while greater than 2 digits

The challenge is to sum the digits of a given number till the result has only one digit. Let say the number is "999" (9+9+9=27, 2+7=9). This is what I did till now.
#!/bin/bash
set +m
shopt -s lastpipe
NUMBER=999
DIGITS=`echo "${#NUMBER}"`
FINALSUM=0
if [ "$DIGITS" -gt 0 ] && [ "$DIGITS" -gt 1 ]; then
grep -o . <<< "${NUMBER}" | while read DIGIT; do
declare -x FINALSUM="$(($FINALSUM+$DIGIT))"
done
echo $FINALSUM
else
echo $SOMA
fi
A bit slow for large numbers:
function sumit {
i="$1"
while [ "$i" -gt 10 ]; do
(( i=i%10 + i/10 ))
done
echo "$1 => $i"
}
# Test
for i in 10 15 999 222 2229; do
sumit $i
done
Can an awk-ward guy join in?
$ awk -v i=999 '
BEGIN {
while( split(i,a,"") > 1) {
i=0;
for( j in a ) i+=a[j]
}
print i
}'
9

reset counter in while loop bash

I'm struggling with this script, I have tried different thing but I can't get it to work.
I tried with if ,doesn't work, I tried with nested while also without success. I don't know what to do any more...
If the value imax has reached 10 i want it to start over with 1
this is the code:
folder="f"
ps=20000
name="test"
i=1
imax=1
while [ $i -le 20 ]
do
cd
cd "$folder$((i))"
sed -i 1s/.*/$name$((imax))/ file.txt
sed -i 2s/.*/$ps/ file.txt
(( i++ ))
(( imax++ ))
done
Thank you
Something like this works:
i=1
imax=1
while [ $i -le 20 ]
do
echo $i $imax
(( i++ ))
(( imax++ ))
if [ $imax -eq 10 ]; then imax=1; fi
done

Syntax error near unexpected token `if' in shell scripting

I was trying a sample program, to check the odd and even no's and was getting an error as below,
#!/bin/bash
N=10
for i in 1..N
if [$i/2 == 0]
then
echo "even"
else
echo "Odd"
fi
Error:
./case.sh: line 5: syntax error near unexpected token `if'
./case.sh: line 5: `if [$i/2 == 0]'
EDITED :
#!/bin/bash
N=10
for i in 1..N
do
if(( ($i/2) == 0 ));
then
echo "even"
else
echo "Odd"
fi
done
error :
./case.sh: line 6: ((: (1..N/2) == 0 : syntax error: invalid arithmetic operator (error token is "..N/2) == 0 ")
Odd
Correct working code :
#!/bin/bash
N=3
for (( i=1; i <= N; i++ ));
#for i in 1..N; // This didnt work
do
if [[ $i/2 -eq 0 ]]
#if (( i/2 == 0 )); // This also worked
then
echo "even"
else
echo "Odd"
fi
done
[ ] or [[ ]] needs spaces between its arguments. And in your case you should use [[ ]] or (( )) as [ ] can't handle division along with comparison:
if [[ 'i / 2' -eq 0 ]]; then
if (( (i / 2) == 0 )); then
for i in 1..N; do should also be
for (( i = 1; i <= N; ++i )); do
You probably meant to have a form of brace expansion, but you can't apply a parameter name on it:
{1..10} ## This will work.
{1..N} ## This will not work.
Using eval may fix it but better go for the other form of for loop instead.
Try this :
#!/bin/bash
N=10
for i in $(seq 1 $N); do
if [ `expr $i % 2` -eq 0 ]
then
echo "even"
else
echo "Odd"
fi
done
1..N is not a valid syntax in bash(though I think you might be coming from ruby background), you can use seq.

Numerical if statement in a Bash Script using $'s

I have written a short Bash Script:
for j in 0 1 2 3 4 5
do
for (( i=$j; i <= 5; i++ ));
do
if [ $(($(($i - $j)) > 1)) ]; then
echo "True"
else
echo "False"
fi
done
done
I expect this script to output a mixture of Trues and Falses however it only outputs Trues. I have checked and seen that $(($(($i - $j)) > 1)) is correctly producing 0s and 1s as it is supposed to but apparently the if statement is not registering these and always assumes "True".
Am I missing something in my code?
Thank you very much
James
Your script is checking if [ 0 ] and if [ 1 ] which isn't what you think. It will always return true because it is checking that the length of the string 0 and 1 is not zero.
Change it to:
for j in {0..5}
do
for (( i=j; i<=5; i++ ))
do
if (( i - j > 1 ))
then
echo True
else
echo False
fi
done
done
Note that the use of the $ prefix for variables within ((...)) is optional.
You're using if incorrectly, you're testing for string length when you want an arithmetic comparison:
for j in {0..5}; do
for i in $(seq $j 5); do
if (( i - j > 1 )); then
echo "True"
else
echo "False"
fi
done
done

Resources