LinuxQuestions.org
Review your favorite Linux distribution.
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-04-2008, 05:08 PM   #1
frenchn00b
Senior Member
 
Registered: Jun 2007
Location: E.U., Mountains :-)
Distribution: Debian, Etch, the greatest
Posts: 2,546

Rep: Reputation: 51
bash/sh: global or local variable with for (loop) isssue


Hello,

I wanna prepare for growisofs, with taking the files, removing space, and to put them not in column but in line.

my code is:

Code:
 ls -1 | sedremovespace  | while read GL ; do FINAL="$FINAL $GL " ; done ; echo "$FINAL"
returns nothing because FINAL is empty


with /usr/bin/sedremovespace:
Code:
sed 's/\ /\\\ /g'
Would anyone have any ideas. Thank you!
 
Old 11-04-2008, 06:33 PM   #2
jlinkels
Senior Member
 
Registered: Oct 2003
Location: Bonaire
Distribution: Debian Lenny/Squeeze/Wheezy/Sid
Posts: 4,166

Rep: Reputation: 506Reputation: 506Reputation: 506Reputation: 506Reputation: 506Reputation: 506
Removed the post because of an embarrassing mistake.

Last edited by jlinkels; 11-05-2008 at 07:28 PM.
 
Old 11-05-2008, 03:08 PM   #3
jan61
Member
 
Registered: Jun 2008
Posts: 235

Rep: Reputation: 46
Moin,

every pipe creates a subshell and that's why nothing you assign to a variable after a pipe is visible outside. It's a common mistake: A variable can't be exported from a subshell to the parent shell.

You can do it like this (look here for explanations: http://www.jan-trippler.de/en/script...variables.html):

Code:
FINAL="`ls -1 | sedremovespace  | while read GL; do echo -n \"$GL \"; done`"
Jan

EDIT: But there's an even more simplier way: You don't need the read loop.
Code:
FINAL="`ls -1 | sedremovespace`"

Last edited by jan61; 04-18-2009 at 12:30 PM.
 
1 members found this post helpful.
Old 11-05-2008, 03:55 PM   #4
frenchn00b
Senior Member
 
Registered: Jun 2007
Location: E.U., Mountains :-)
Distribution: Debian, Etch, the greatest
Posts: 2,546

Original Poster
Rep: Reputation: 51
Code:
      #!/bin/bash 
         counter=0 ; ls -1 | while read n ; do let counter+=1 ; done ; 
         echo $counter
LOOKS IMPOSSIBLE !!
cuz echo $counter returns nothing
 
Old 11-05-2008, 05:45 PM   #5
chrism01
Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Centos 6.5, Centos 5.10
Posts: 16,289

Rep: Reputation: 2034Reputation: 2034Reputation: 2034Reputation: 2034Reputation: 2034Reputation: 2034Reputation: 2034Reputation: 2034Reputation: 2034Reputation: 2034Reputation: 2034
Like Jan61 said
Quote:
every pipe creates a subshell and that's why nothing you assign to a variable after a pipe is visible outside.
You need a different technique eg
Code:
counter=0
for file in `ls`
do
    let counter+=1
done
echo $counter
 
Old 11-06-2008, 12:34 AM   #6
frenchn00b
Senior Member
 
Registered: Jun 2007
Location: E.U., Mountains :-)
Distribution: Debian, Etch, the greatest
Posts: 2,546

Original Poster
Rep: Reputation: 51
Quote:
Originally Posted by chrism01 View Post
Like Jan61 said

You need a different technique eg
Code:
counter=0
for file in `ls`
do
    let counter+=1
done
echo $counter
The big problem is this one with files :

if cat /tmp/files.tmp
Code:
/home/french/the file with spaces.doc
/home/french/the file with spaces222 333.doc
/home/french/thefile.doc
/home/french/the file with spaces222 333 5555.doc

Code:
counter=0
for file in `cat /tmp/files.tmp`
do
    let counter+=1
    echo `du -b "$file" | tail -n 1 | cut -f 1`
done
echo $counter

then your script doesnt work because for / "$file" are messed up with spaces and not LF/chr(10)chr(13)



Help please
 
Old 11-06-2008, 01:40 AM   #7
chrism01
Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Centos 6.5, Centos 5.10
Posts: 16,289

Rep: Reputation: 2034Reputation: 2034Reputation: 2034Reputation: 2034Reputation: 2034Reputation: 2034Reputation: 2034Reputation: 2034Reputation: 2034Reputation: 2034Reputation: 2034
In that case, set the IFS to a newline only at the start.
http://tldp.org/LDP/abs/html/internalvariables.html
 
Old 11-06-2008, 02:33 AM   #8
jlliagre
Moderator
 
Registered: Feb 2004
Location: Outside Paris
Distribution: Solaris10, Solaris 11, Mint, OL
Posts: 9,507

Rep: Reputation: 360Reputation: 360Reputation: 360Reputation: 360
Quote:
Originally Posted by frenchn00b View Post
Code:
      #!/bin/bash 
         counter=0 ; ls -1 | while read n ; do let counter+=1 ; done ; 
         echo $counter
LOOKS IMPOSSIBLE !!
cuz echo $counter returns nothing
Your script works fine if you replace /bin/bash by /bin/ksh or /bin/zsh.
In my opinion, bash developers took an unfortunate decision when choosing which part of a pipeline would be run in a subshell.
 
Old 11-06-2008, 06:17 AM   #9
jlinkels
Senior Member
 
Registered: Oct 2003
Location: Bonaire
Distribution: Debian Lenny/Squeeze/Wheezy/Sid
Posts: 4,166

Rep: Reputation: 506Reputation: 506Reputation: 506Reputation: 506Reputation: 506Reputation: 506
Quote:
Originally Posted by jlliagre View Post
In my opinion, bash developers took an unfortunate decision when choosing which part of a pipeline would be run in a subshell.
Not so much the decision where to start the subshell is bad (*nix contains more very rigid orthogonalities which you have to learn to live with, either good or bad) but incompatibility between the shells is disastrous in my opinion. It doesn't only mean that this script runs the way it is intended in other shells while not in bash, it also means that scripts which run in bash using this property may crash or give unintentional results in other shells.

As for this particular script, I don't see the use for piping. I have seen a few of this similar problems over the past few months which all concerned piping into a loop. Piping the result of one program into another (like
Code:
cat myfile | grep foo | sed s/foo/bar/g
is logical and harmless. Piping into a loop
Code:
ls -1 | while read .... done
might be syntactically correct and executable, it still is not elegant programming. It is awkward to have one statement producing one result, and feed that into a repetitive loop using a part of that result bit by bit, without you are clearly aware of doing that. This is clearly different from, for example, producing a string and parse it by token in the next loop.
The example chrism01 provided is much cleaner, provides hooks for debugging and makes the code obvious and understandable. Maybe programmers should be discouraged of using pipes in this manner anyway.


jlinkels
 
Old 11-06-2008, 07:24 AM   #10
jlliagre
Moderator
 
Registered: Feb 2004
Location: Outside Paris
Distribution: Solaris10, Solaris 11, Mint, OL
Posts: 9,507

Rep: Reputation: 360Reputation: 360Reputation: 360Reputation: 360
Quote:
Originally Posted by jlinkels View Post
Not so much the decision where to start the subshell is bad (*nix contains more very rigid orthogonalities which you have to learn to live with, either good or bad) but incompatibility between the shells is disastrous in my opinion.
These are different points.
Either you explicitely specify the shell you use (bash, ksh, zsh, whatever) and you are free to take advantage of their specific enhancements.
Either you want to write portable scripts and you need to stick to POSIX shell statements and syntax.
What is unfortunate in that specific pipe subshell case is POSIX didn't choose to follow ksh (which was the model for most features) and let that choice implementation dependent. Scripts that rely on variable sets in pipeline components are thus all non portable.
Quote:
It doesn't only mean that this script runs the way it is intended in other shells while not in bash, it also means that scripts which run in bash using this property may crash or give unintentional results in other shells.
True, but the interpreter should be specified to avoid the risk.
Quote:
As for this particular script, I don't see the use for piping.
Yes. I just pointed it as an example.
Quote:
I have seen a few of this similar problems over the past few months which all concerned piping into a loop. Piping the result of one program into another (like
Code:
cat myfile | grep foo | sed s/foo/bar/g
is logical and harmless.
Harmless but far to be optimized. Both cat and grep are unnecessary:
Code:
sed -n 's/foo/bar/gp' myfile
 
  


Reply


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
how to loop over text file lines within bash script for loop? johnpaulodonnell Linux - Newbie 8 04-05-2011 09:18 AM
bash loop within a loop for mysql ops br8kwall Programming 10 04-30-2008 03:50 AM
Using global variable in awk (bash script) kopeda Programming 2 04-24-2007 01:47 AM
Bash Local Variable Recursion With Array jshivers Programming 0 06-16-2006 04:31 PM
python global variable? goestin Programming 1 01-20-2005 06:52 AM


All times are GMT -5. The time now is 11:49 AM.

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