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 |
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
 |
GNU/Linux Basic Guide
This 255-page guide will provide you with the keys to understand the philosophy of free software, teach you how to use and handle it, and give you the tools required to move easily in the world of GNU/Linux. Many users and administrators will be taking their first steps with this GNU/Linux Basic guide and it will show you how to approach and solve the problems you encounter.
Click Here to receive this Complete Guide absolutely free. |
|
 |
11-04-2008, 05:08 PM
|
#1
|
|
Senior Member
Registered: Jun 2007
Location: E.U., Mountains :-)
Distribution: Debian, Etch, the greatest
Posts: 2,546
Rep:
|
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:
Would anyone have any ideas. Thank you!
|
|
|
|
11-04-2008, 06:33 PM
|
#2
|
|
Senior Member
Registered: Oct 2003
Location: Bonaire
Distribution: Debian Lenny/Squeeze/Wheezy/Sid
Posts: 3,832
|
Removed the post because of an embarrassing mistake.
Last edited by jlinkels; 11-05-2008 at 07:28 PM.
|
|
|
|
11-05-2008, 03:08 PM
|
#3
|
|
Member
Registered: Jun 2008
Posts: 235
Rep:
|
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.
|
11-05-2008, 03:55 PM
|
#4
|
|
Senior Member
Registered: Jun 2007
Location: E.U., Mountains :-)
Distribution: Debian, Etch, the greatest
Posts: 2,546
Original Poster
Rep:
|
Code:
#!/bin/bash
counter=0 ; ls -1 | while read n ; do let counter+=1 ; done ;
echo $counter
LOOKS IMPOSSIBLE !!
cuz echo $counter returns nothing
|
|
|
|
11-05-2008, 05:45 PM
|
#5
|
|
Guru
Registered: Aug 2004
Location: Brisbane
Distribution: Centos 6.4, Centos 5.9
Posts: 15,261
|
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
|
|
|
|
11-06-2008, 12:34 AM
|
#6
|
|
Senior Member
Registered: Jun 2007
Location: E.U., Mountains :-)
Distribution: Debian, Etch, the greatest
Posts: 2,546
Original Poster
Rep:
|
Quote:
Originally Posted by chrism01
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
|
|
|
|
11-06-2008, 02:33 AM
|
#8
|
|
Moderator
Registered: Feb 2004
Location: Outside Paris
Distribution: Solaris10, Solaris 11, Mint, OL
Posts: 9,325
|
Quote:
Originally Posted by frenchn00b
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.
|
|
|
|
11-06-2008, 06:17 AM
|
#9
|
|
Senior Member
Registered: Oct 2003
Location: Bonaire
Distribution: Debian Lenny/Squeeze/Wheezy/Sid
Posts: 3,832
|
Quote:
Originally Posted by jlliagre
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
|
|
|
|
11-06-2008, 07:24 AM
|
#10
|
|
Moderator
Registered: Feb 2004
Location: Outside Paris
Distribution: Solaris10, Solaris 11, Mint, OL
Posts: 9,325
|
Quote:
Originally Posted by jlinkels
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
|
|
|
|
| Thread Tools |
Search this Thread |
|
|
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -5. The time now is 05:06 PM.
|
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|