While loop never ends - bash

I'm working with bash and I'm trying to do something like this:
A=1
while [ $A=1 ]; do
read line
echo $line | grep test >/dev/null
A=$?
echo $A
done
This script never ends even when the grep finishes successfully and A is set to 0. What am I missing here? Below is a sample of the output.
$ ./test.sh
asdf
1
test
0
hm...
1

You need to use the correct comparison operator. Bash has different operators for integer and string comparison.
In addition, you need the correct spacing in the comparison expression.
You need
while [ $A -eq 1 ]; do
See here for more

I find Bash's syntax pretty awful - have you tried something like:
while [ $A -eq 1 ] ... ?
It may be trying to re-assign 1 to $A or something strange like that.

Try:
while [ $A -eq 1 ]; do

Most of the answers have focused on the integer/string and spacing problem, which is fine, but your code looks so unidiomatic that IMO it should be completely re-factored. Let's say the idea is to process lines until one line matches the regex 'test':
while read line; do
if [[ "$line" =~ test ]] && break
# do something with $line
done
Of course this can be simplified further if you take advantage of text processing tools like sed:
sed -e '/test/,$d'

you can do this instead. No need to call external grep.
while true; do
read line
case "$line" in
*test* ) break;;
esac
done
echo $line

Have you not tried this
while [ $A == "1" ]
....
done
Edit: Whoops since Dan mentioned my error I graciously admit my mistake and have edited this accordingly - Thanks Dan for the heads up...
while [ $A -eq 1 ]
....
done
Sorry! :(
Hope this helps,
Best regards,
Tom.

All of your answers are in the Advanced Bash-Scripting guide. It is awesome.

Related

While loop in Bash not running

I'm pretty new with Bash scripting and am having trouble getting my 'while' loop to run. When I echo keywords, a whole list of words prints and then when I echo length, it prints 124. I believe I'm using the while loop and condition correctly, so I can't figure out what I'm doing wrong. Any thoughts?
keywords=$1
length=${#keywords}
echo "$keywords"
echo "$length"
if [ -z "$keywords" ]; then
while [ $length -gt 100 ]; do
echo "$keywords"
echo "$length"
keywords="${keywords%,*}"
length=${#keywords}
done
fi
echo $keywords
The problem is here:
[ -z "$keywords" ]
-z is true if its argument is an empty string. Something of length 124 is definitely far from empty. You probably meant -n.
Next time, please also include the input in the question so we can reproduce the problem.

Bash IF statement

rather noobie question here.. i think. but i cant get this script to work. It is going to be included inside a script that i asked about here a few days ago (BASH output column formatting). basically i want to be able to scrape a site for a portion of text and return a ONLINE/OFFLINE answer. I apologize for poor formatting and weird variable names. Thanks for taking a look and helping me out!
#!/bin/bash
printf "" > /Users/USER12/Desktop/domainQueryString_output.txt
domainCurlRequest="curl https://www.google.com/?gws_rd=ssl"
ifStatementConditional="grep 'google.com' /Users/USER12/Desktop/domainQueryString_output.txt | wc -l"
echo $($domainCurlRequest) >> /Users/USER12/Desktop/domainQueryString_output.txt
if [ $ifStatementConditional -eq 2 ] ;
then second_check="online"
else second_check="DOMAIN IS OFFLINE"
fi
echo $second_check
i keep getting the following error when trying to run this script
/Users/USER12/Desktop/domain_status8working.sh: line 6: [: too many arguments
i tried to rewrite another way but got same errors so my logic or syntax or something is off.
Thanks again for taking a look and helping me out!!!
ifStatementConditional="grep 'google.com' /Users/USER12/Desktop/domainQueryString_output.txt | wc -l"
This is a string assignment. You probably want backticks, or the $() construct. Otherwise, $ifStatementConditional will never equal 2
if [ $ifStatementConditional -eq 2 ] ;
This is expanded as:
if [ grep 'google.com' /Users/USER12/Desktop/domainQueryString_output.txt | wc -l -eq 2 ] ;
Which explains your error.
I think you meant that:
#!/bin/bash
curl "https://www.google.com/?gws_rd=ssl" > /Users/USER12/Desktop/domainQueryString_output.txt
ifStatementConditional=$("grep 'google.com' /Users/USER12/Desktop/domainQueryString_output.txt | wc -l")
if [ $ifStatementConditional -eq 2 ] ; then
second_check="online"
else
second_check="DOMAIN IS OFFLINE"
fi
echo $second_check
No need to do printf "" > somefile.txt when you do a curl after, and you append to that file
$() is to capture subshell output. That what was missing here.

Removing files in Unix using bash

I'm trying to delete a large amount of files from my computer, and I'm trying to write a bash script to do so using the rm command. What I want to know is how to do equality in bash, and why my code (posted below) won't compile. Thank you for your help!
#!/bin/bash
# int-or-string.sh
b="0000"
c="linorm"
f=500
e1=2
e2=20
e3=200
e4=2000
for i in {0..10000}
do
a=$(($f*$i))
if ["$i" -eq "$e1"]
then
b="000"
echo $b$
fi
if ["$i" -eq "$e2"]
then
b='00'
fi
if ["$i" -eq "$e3"]
then
b='0'
fi
if ["$i" -eq "$e4"]
then
b =''
fi
if [bash$ expr "$i" % "$e3$ -ne 0]
then
d = $b$c$a
rm d
fi
done
Shell scripts aren't compiled at all.
You need spaces after your [ and before your ].
if [ "$i" -eq "$e1" ]
There's an errant bash$ in there you probably don't want at all. It should probably be a $() operator:
if [ $(expr "$i" % "$e3") -ne 0 ]
You can't have spaces around the = in bash. For example, change b ='' to b='' and d = $b$c$a to d=$b$c$a.
echo $b$ looks like it should be echo $b.
Shell script does not compile it is a scripting language.
Try to fix this line :
if [bash$ expr "$i" % "$e3$ -ne 0]
Make it like below :
if [ $(expr "$i" % "$e3$") -ne 0 ]
You need spaces around the square brackets. The [ is actually a command, and like all commands needs to be delineated by white space.
When you set values for variables in shell, you do not put spaces around the equals signs.
Use quotation marks when doing comparisons and setting values to help delineate your values.
What happens if none of the if conditions are true, and $b isn't set.
What is the logic behind this code. It seems to be a bunch of random stuff. You're incrementing $ from 1 to 10000, but only setting the value of $b on only four of those values. Every 200 steps, you delete a file, but $b may or may not be set even though it's part of the file name.
Did you write this program yourself? Did you try to run it? What errors were you getting? Did you look at the lines referenced by those errors. It looks like you included the bash$ prompt as part of the command.
There were plenty of errors, and I've cleaned most of them up. The cleaned up code is posted below, but it still doesn't mean it will do what you want. All you said is you want to delete "a large amount of files" on your computer, but gave no other criteria. You also said "What I want to know is how to do equality in bash" which is not the question you stated in you header.
Here's the code. Note the changes, and it might lead to whatever answer you were looking for.
#!/bin/bash
# int-or-string.sh
b="0000"
c="linorm"
f=500
e1=2
e2=20
e3=200
e4=2000
for i in {0..10000}
do
a=$(($f*$i))
if [ "$i" -eq "$e1" ]
then
b="000"
elif [ "$i" -eq "$e2" ]
then
b='00'
elif [ "$i" -eq "$e3" ]
then
b='0'
elif [ "$i" -eq "$e4" ]
then
b=''
fi
if ! $(($i % $e3))
then
d="$b$c$a"
rm "$d"
fi
done
ERRORS:
Spaces around the [ and ]
The rm "$d" command was originallyrm dwhich would just remove a file namedd`.
if/then statement converted to if/else if.
Rewrote [ $(expr "$1" % "$e3") -ne 0 ].
No need for expr since BASH has $((..)) syntax.
No need for test command ([) since if automatically evaluates zero to true and non-zero to false.
Added quotes.

if statement numerical confusion in bash/sh

I've been arguing with this code all morning. It finally dawned on me, upon reading TL;DP that my if statements may be confusing output redirection with a comparison.
The code in question is:
#!/bin/sh
...
if [ $DEBUG_LEVEL > 2 ]
then
echo "I made it here"
echo "DEBUG: created run_all_somatic_SNV_steps" >>$LOG
fi
Is my if statement confusing stderr redirection with what I want it to do? (compare a variable to the number 2)
For general shell:
if [ $DEBUG_LEVEL -gt 2 ]
(But that will fail if DEBUG_LEVEL has never been set.)
More bash-specific, and a lot nicer:
if (( DEBUG_LEVEL > 2 ))
try this test construct:
[ $DEBUG_LEVEL -gt 2 ]

shell script variable use

I'll get to the meat and bones:
MY_VAR=6
until [$MY_VAR = 0]
do
dir/dir_$MY_VAR.log
ps | grep "NAME_$MY_VAR.ksh"
check some things
if [results = ok]
echo "program $MY_VAR sucessful"
else
echo "program $MY_VAR failure"
MY_VAR = `expr $MY_VAR - 1`
done
Now I am getting the following errors MY_VAR not found and [6: not found, so I'm assuming a rather noobish mistake. I feel the logic is sound enough just a simple syntax error I am making somewhere by the looks of the two errors I think it could be in the declaration.
You need to have a space after [ and before ] since [ is actually a command and not a delimiter.
Here is your script re-written in Bash (or ksh):
my_var=6
until ((my_var == 0))
do
dir/dir_$my_var.log # I have no idea what this is supposed to be
ps | grep "NAME_$my_var.ksh"
# check some things
if [[ $results = ok ]]
then
echo "program $my_var successful"
else
echo "program $my_var failure"
((my_var--))
fi
done
However:
for my_var in {6..1}
do
dir/dir_$my_var.log # I have no idea what this is supposed to be
ps | grep "NAME_$my_var.ksh"
# check some things
if [[ $results = ok ]]
then
echo "program $my_var successful"
else
echo "program $my_var failure"
fi
done
Your two errors are caused by:
until [$MY_VAR = 0]
MY_VAR = $(expr $MY_VAR - 1)
[I've used $() instead of backticks because I couldn't get backticks into the code section]
The first problem is the lack of spaces around the square brackets - on both ends. The shell is looking for the command [6 (after expanding $MY_VAR), instead of [ (have a look at /usr/bin/[ - it's actually a program). You should also use -eq to do numeric comparisons. = should work ok here, but leading zeros can break a string comparison where a numeric comparison would work:
until [ "$MY_VAR" -eq 0 ]
The second problem is you have spaces in your variable assignment. When you write MY_VAR = ... the shell is looking for the command MY_VAR. Instead write it as:
MY_VAR=`expr $MY_VAR - 1`
These answers directly answer your questions, but you should study Dennis Williamson's answer for better ways to do these things.

Resources