LinuxQuestions.org
Go Job Hunting at the LQ Job Marketplace
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices



Reply
 
Search this Thread
Old 11-10-2006, 09:47 PM   #1
fatsheep
Member
 
Registered: Sep 2006
Posts: 79

Rep: Reputation: 15
How to define a variable In a while loop?


I'm writing a bash package management script and I have a variable, $conflict, that is set to "1" if a system-package conflict exists (the system contains the same files that the package does). Here's the loop where the script checks for conflicts:

Code:
#### CHECK FOR PACKAGE - SYSTEM CONFLICTS
#### Set $conflict to "1" if a conflict exists.

find | \
# Outputs all files and directories under the PWD.
sed "/\.$/d" | \
# Deletes the current directory (.) entry.
sed "s@^.@@" | \
# Removes the "." char from the beginning of all the file paths

while read file ; do
echo 'Entering Loop #1'

#echo "\$file = $file"

sysFile=`echo $file | sed "s@^@$sysRoot@"`
pkgFile=`echo $file | sed "s@^@$pkgPath@"`

#echo '$sysFile =' $sysFile
#echo '$pkgFile =' $pkgFile

if [ -d $pkgFile ] && [ -e $sysFile ] && ! [ -d $sysFile ] ; then

	echo "ERROR: $sysFile exists!"
	conflict="1"
	break

fi


if ! [ -d $pkgFile ] && [ -e $sysFile ] ; then
		
	echo "ERROR: $sysFile exists!"
	conflict="1"
	break
	
fi

echo 'Exiting Loop #1'

echo $conflict
done
My problem is that when I set $conflict to "1", it only remains "1" within the loop. Right after the break command, it returns to the default value which I defined at the beginning of the script: "0". How would I make a global change to the variable (meaning that it will = "1" throughout the script)?

Last edited by fatsheep; 11-10-2006 at 09:57 PM.
 
Old 11-10-2006, 10:17 PM   #2
dxqcanada
Member
 
Registered: Sep 2006
Location: Canada
Distribution: Gentoo
Posts: 702

Rep: Reputation: 43
Shouldn't the
echo $conflict
be outside of the while loop ?

Last edited by dxqcanada; 11-10-2006 at 10:18 PM.
 
Old 11-10-2006, 10:25 PM   #3
fatsheep
Member
 
Registered: Sep 2006
Posts: 79

Original Poster
Rep: Reputation: 15
Quote:
Originally Posted by dxqcanada
Shouldn't the
echo $conflict
be outside of the while loop ?
There's one outside of the loop as well, I just didn't include that segment.
 
Old 11-10-2006, 10:32 PM   #4
dxqcanada
Member
 
Registered: Sep 2006
Location: Canada
Distribution: Gentoo
Posts: 702

Rep: Reputation: 43
Since you are breaking out of the loop the echo $conflict that is in the loop will show "0" (since conflict only get set to 1 before breaking out of the loop.

The echo $conflict that is outside of the loop should show "1" if the condition is met.

This simple script will show you"

Code:
#!/bin/bash
conflict=0
while read input
do
if [ $input = 0 ]
then
conflict=1
break
fi
echo conflict inside is $conflict
done
echo conflict outside is $confict
 
Old 11-10-2006, 10:33 PM   #5
kr4m3r
LQ Newbie
 
Registered: Nov 2006
Location: san.rr.com
Distribution: Gentoo 2006.0
Posts: 9

Rep: Reputation: 0
Perhaps try to "define" the variable before the loop?
 
Old 11-10-2006, 10:58 PM   #6
duryodhan
Senior Member
 
Registered: Oct 2006
Distribution: Slackware 12 Kernel 2.6.24 - probably upgraded by now
Posts: 1,054

Rep: Reputation: 46
ya I guess, just do conflict=0 before beginning of while loop.
 
Old 11-11-2006, 12:43 PM   #7
fatsheep
Member
 
Registered: Sep 2006
Posts: 79

Original Poster
Rep: Reputation: 15
Quote:
Originally Posted by dxqcanada
Since you are breaking out of the loop the echo $conflict that is in the loop will show "0" (since conflict only get set to 1 before breaking out of the loop.

The echo $conflict that is outside of the loop should show "1" if the condition is met.

This simple script will show you"

Code:
#!/bin/bash
conflict=0
while read input
do
if [ $input = 0 ]
then
conflict=1
break
fi
echo conflict inside is $conflict
done
echo conflict outside is $confict
That example returned errors... Not sure why but here's my edited code:

Code:
#!/bin/bash

# $conflict will be set to "1" if conflict exists
conflict="0"
echo $conflict

sysRoot="/home/ubuntu/Desktop/sources/sysRoot"
rootPkgDir="/home/ubuntu/Desktop/sources/pkg"
pkg="lynx-2.8.6"
pkgPath="$rootPkgDir/$pkg"
#pkgPath="/home/ubuntu/Desktop/sources/pkg/lynx-2.8.6"

echo '$rootPkgDir = ' $rootPkgDir
echo '$pkg = ' $pkg
echo '$pkgPath = ' $pkgPath

cd $pkgPath




#### CHECK FOR PACKAGE - SYSTEM CONFLICTS
#### Set $conflict to "1" if a conflict exists.

find | \
# Outputs all files and directories under the PWD.
sed "/\.$/d" | \
# Deletes the current directory (.) entry.
sed "s@^.@@" | \
# Removes the "." char from the beginning of all the file paths

while read file ; do
#echo 'Entering Loop #1'

#echo "\$file = $file"

sysFile=`echo $file | sed "s@^@$sysRoot@"`
pkgFile=`echo $file | sed "s@^@$pkgPath@"`

#echo '$sysFile =' $sysFile
#echo '$pkgFile =' $pkgFile

if [ -d $pkgFile ] && [ -e $sysFile ] && [ ! -d $sysFile ] ; then

	echo "ERROR#1: $sysFile exists."
	conflict="1"
	echo "Setting \$conflict to \"1\""
	echo $conflict
	break

fi


if [ ! -d $pkgFile ] && [ -e $sysFile ] ; then
		
	echo "ERROR#2: $sysFile exists."
	conflict="1"
	echo "Setting \$conflict to \"1\""
	echo $conflict
	break
	
fi

#echo 'Exiting Loop #1'

done

echo '$conflict =' $conflict "outside the loop."
Here's the output when I run the script:

Quote:
0
$rootPkgDir = /home/ubuntu/Desktop/sources/pkg
$pkg = lynx-2.8.6
$pkgPath = /home/ubuntu/Desktop/sources/pkg/lynx-2.8.6
ERROR#2: /home/ubuntu/Desktop/sources/sysRoot/usr/bin/lynx exists.
Setting $conflict to "1"
1
$conflict = 0 outside the loop.
as you can see, the second if statement evaluates as true ( I have set up a conflict on purpose to test it). Then $conflict is set to "1". I echo conflict inside the if statement, it returns the value "1". Then I issue the break command to exit the loop. Outside the loop, I echo $conflict, this time it evaluates as "0". Why?
 
Old 11-11-2006, 07:39 PM   #8
ygloo
Member
 
Registered: Aug 2006
Distribution: slack
Posts: 323

Rep: Reputation: 30
it seems to me that variable keeps its value within the loop...
try "export $conflict " and echo $conflict ( to see the value)... inside the loop
 
Old 11-11-2006, 07:51 PM   #9
randyding
Member
 
Registered: May 2004
Posts: 552

Rep: Reputation: 31
The problem is the pipe. When you pipe a new instance of the shell is executed as a separate process to receive data on stdin. When you make a variable assignment inside this new pipe process the variable is lost when the process exits at the end of the pipe.
 
Old 11-11-2006, 08:21 PM   #10
ygloo
Member
 
Registered: Aug 2006
Distribution: slack
Posts: 323

Rep: Reputation: 30
Quote:
My problem is that when I set $conflict to "1", it only remains "1" within the loop. Right after the break command, it returns to the default value which I defined at the beginning of the script: "0". How would I make a global change to the variable (meaning that it will = "1" throughout the script)?
try declare -r conflict=1

"
-r Make variables read-only. These variables cannot then be assigned values by subsequent assignment statements, nor can they be unset.
"

Last edited by ygloo; 11-11-2006 at 08:22 PM.
 
Old 11-12-2006, 10:24 AM   #11
randyding
Member
 
Registered: May 2004
Posts: 552

Rep: Reputation: 31
Here's a short example that demonstrates your situation.
Code:
#!/bin/bash

linenum=0
echo -en "hello\nworld\n" | while read x; do
    linenum=$((linenum+1))
    echo "$linenum: $x"
done
echo "total number of lines = $linenum"

It then prints out...
1: hello
2: world
total number of lines = 0
The problem is you want the total number of lines to be printed as 2. This can not be done with a variable assignment in the loop because the pipe ( | while read ...) runs in a separate process.
 
Old 11-12-2006, 03:36 PM   #12
aluser
Member
 
Registered: Mar 2004
Location: Massachusetts
Distribution: Debian
Posts: 557

Rep: Reputation: 42
A workaround is to put the entire "stuff | while blah; do halb; done" construct inside backquotes and echo $conflict at the end. i.e.
Code:
conflict=`stuff | ( while blah; do whatever; done; echo $conflict )`
Be sure to echo any errors found inside the subshell to stderr like
Code:
echo >&2 "Oh no Mr. Bill!"
so that they aren't captured by the backquotes
 
Old 03-01-2012, 02:12 AM   #13
hpal
LQ Newbie
 
Registered: Mar 2012
Posts: 1

Rep: Reputation: Disabled
We have the same problem about variable scoping, since I also need to get the presently login user and then, check if corresponding user belongs to a group.

I have wrote several test code with regards to variable scoping outside while loop. But, I could not find any related variable declaration to make the variable value within WHILE loop, I also use export and using extra conditions. The result leads me to conclude that variable within While Loop is only accessible from within the loop itself.

So, I decided to save the value to a file then read it back outside the while loop -- it resolves my problem, please see below code if you could find it useful:


whoami | while read line; do
#if [[ "$userName" = "" ]] ; then
userName=$line
#fi
echo $userName
if [ ! $userName == "" ]; then
echo "userName=$userName" > ~/getuser.bash
break
fi
done
chmod 755 ~/getuser.bash
echo "username value outside while loop=$userName"

if [ -f getuser.bash ] ; then
source getuser.bash
fi
echo "username value outside while loop in getuser.bash file=$userName"

Output:
username value outside while loop=
username value outside while loop in getuser.bash file=hpal
 
Old 03-01-2012, 04:56 PM   #14
rknichols
Senior Member
 
Registered: Aug 2009
Distribution: CentOS
Posts: 1,548

Rep: Reputation: 642Reputation: 642Reputation: 642Reputation: 642Reputation: 642Reputation: 642
@hpal -- You are responding to a thread that is over 5 years old. The OP either solved his problem or gave up long ago.
 
Old 03-02-2012, 11:40 AM   #15
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: FreeBSD, Debian, Mint, Puppy
Posts: 3,298

Rep: Reputation: 175Reputation: 175
or dead.
but FYI use export:

Code:
$ export x=fish
$ echo $x
fish
$ while :;do x=chips;break;done
$ echo $x
chips
 
1 members found this post helpful.
  


Reply

Tags
bash, loop, management, package, variable


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Define global variable maxmil Linux - Newbie 4 03-07-2006 11:36 AM
How can I define a global variable? kloss Linux - General 4 02-21-2006 05:30 AM
diff between #define and const defined variable b123coder Programming 7 06-27-2005 09:02 AM
how am i define an environment variable? yenonn Slackware 2 12-19-2003 08:44 AM
how to define a global variable Anniebaby Programming 1 11-09-2003 11:43 PM


All times are GMT -5. The time now is 06:04 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration