In this group, it is an FGA that one should so:
commandThatGeneratesTheFilenames | while read x ...
instead of the more common:
for i in ...
because of the problems of filenames that spaces and other weird characters.
However, one downside to the "while" method is that inside the loop,
stdin is now coming from the pipe, and commands that we execute inside
the loop, that expect a normal stdin, will misbehave.
Workarounds:
1) append "< /dev/tty" to each command
2) enclose the commands in parens and redirect that. I.e.:
commandThatGeneratesTheFilenames | while read x;do
(cmd1;cmd2;cmd3;...) < /dev/tty
done
Method 2 is nice and seems to work fine, but I am wondering if there is
any hidden cost to it and if there is any more elegant/effcient way to
do this.
--
Just for a change of pace, this sig is *not* an obscure reference to
comp.lang.c...
|
|
0
|
|
|
|
Reply
|
gazelle
|
7/20/2010 12:13:50 PM |
|
Kenny McCormack wrote:
> In this group, it is an FGA that one should so:
>
> commandThatGeneratesTheFilenames | while read x ...
>
> instead of the more common:
>
> for i in ...
>
> because of the problems of filenames that spaces and other weird
> characters.
>
> However, one downside to the "while" method is that inside the loop,
> stdin is now coming from the pipe, and commands that we execute inside
> the loop, that expect a normal stdin, will misbehave.
>
> Workarounds:
> 1) append "< /dev/tty" to each command
> 2) enclose the commands in parens and redirect that. I.e.:
>
> commandThatGeneratesTheFilenames | while read x;do
> (cmd1;cmd2;cmd3;...) < /dev/tty
> done
I think (at least with bash) it's possible to use a file descriptor other
than the standard ones, and use read -u to read from that descriptor. This
way, standard descriptors (0, 1 and 2) inside the loop are not affected.
Something like
exec 3< <(command)
while read -u 3 line; do
# unaffected commands here...
done
exec 3>&-
I understand it's a highly nonstandard solution, but, depending on where it
has to run, it might be applicable.
|
|
0
|
|
|
|
Reply
|
pk
|
7/20/2010 12:55:19 PM
|
|
In article <i246br$vjs$1@speranza.aioe.org>, pk <pk@pk.invalid> wrote:
....
>I think (at least with bash) it's possible to use a file descriptor other
>than the standard ones, and use read -u to read from that descriptor. This
>way, standard descriptors (0, 1 and 2) inside the loop are not affected.
>
>Something like
>
>exec 3< <(command)
>
>while read -u 3 line; do
> # unaffected commands here...
>done
>
>exec 3>&-
>
>I understand it's a highly nonstandard solution, but, depending on where it
>has to run, it might be applicable.
Very interesting. As readers of my posts know, I'm not a "standards
jockey", so don't take what I say next as the typical SJ jockeying...
That said,
1) The above works if I invoke "bash" as "bash".
2) (However) It does not work if I invoke "bash" as "sh"
3) It doesn't work under "dash" (which is what /bin/sh on some Linux
boxes actually is).
Anyway, as I said, it is quite intriguing.
--
Just for a change of pace, this sig is *not* an obscure reference to
comp.lang.c...
|
|
0
|
|
|
|
Reply
|
gazelle
|
7/20/2010 2:12:57 PM
|
|
In article <i24at9$rc5$1@news.xmission.com>,
Kenny McCormack <gazelle@shell.xmission.com> wrote:
....
>That said,
> 1) The above works if I invoke "bash" as "bash".
> 2) (However) It does not work if I invoke "bash" as "sh"
> 3) It doesn't work under "dash" (which is what /bin/sh on some Linux
> boxes actually is).
>
>Anyway, as I said, it is quite intriguing.
I forgot to add, the important thing, which is that your solution,
unfortunately, does not work on the targetted system (which is a Linux
system without bash - yes, they exist). So, I am still curious about
the questions raised in the OP - is there any hidden cost (inefficiency)
to using the ()</dev/tty method, and are there any (other) alternatives?
--
"We should always be disposed to believe that which appears to us to be
white is really black, if the hierarchy of the church so decides."
- Saint Ignatius Loyola (1491-1556) Founder of the Jesuit Order -
|
|
0
|
|
|
|
Reply
|
gazelle
|
7/20/2010 2:24:37 PM
|
|
On Tue, 20 Jul 2010 14:12:57 +0000 (UTC) gazelle@shell.xmission.com (Kenny
McCormack) wrote:
> In article <i246br$vjs$1@speranza.aioe.org>, pk <pk@pk.invalid> wrote:
> ...
> >I think (at least with bash) it's possible to use a file descriptor
> >other than the standard ones, and use read -u to read from that
> >descriptor. This way, standard descriptors (0, 1 and 2) inside the loop
> >are not affected.
> >
> >Something like
> >
> >exec 3< <(command)
> >
> >while read -u 3 line; do
> > # unaffected commands here...
> >done
> >
> >exec 3>&-
> >
> >I understand it's a highly nonstandard solution, but, depending on where
> >it has to run, it might be applicable.
>
> Very interesting. As readers of my posts know, I'm not a "standards
> jockey", so don't take what I say next as the typical SJ jockeying...
>
> That said,
> 1) The above works if I invoke "bash" as "bash".
> 2) (However) It does not work if I invoke "bash" as "sh"
> 3) It doesn't work under "dash" (which is what /bin/sh on some Linux
> boxes actually is).
Standards jockey or not, if that is where it has to run, you definitely need
a standard solution.
|
|
0
|
|
|
|
Reply
|
pk
|
7/20/2010 5:06:56 PM
|
|
Kenny McCormack wrote:
> In this group, it is an FGA that one should so:
>
> commandThatGeneratesTheFilenames | while read x ...
>
> instead of the more common:
>
> for i in ...
>
> because of the problems of filenames that spaces and other weird
> characters.
>
> However, one downside to the "while" method is that inside the loop,
> stdin is now coming from the pipe, and commands that we execute inside
> the loop, that expect a normal stdin, will misbehave.
Name one, and I am pretty sure that I can tell you the switch that will
prevent it from considering stdin. For example, ssh(1) has `-n'.
--
PointedEars
|
|
0
|
|
|
|
Reply
|
Thomas
|
7/21/2010 12:14:38 AM
|
|
Kenny McCormack wrote:
> In this group, it is an FGA that one should so:
>
> commandThatGeneratesTheFilenames | while read x ...
>
> instead of the more common:
>
> for i in ...
>
> because of the problems of filenames that spaces and other weird
> characters.
No, the foregone assumption (FGA is not a common Usenet acronym -- shouldn't
that be "foregone conclusion" anyway?) is that find(1) with `-exec', or
`find' with xargs(1), are safer than both approaches.
Usenet rule of thumb: Never ask what is better; bottom line is that better
is what works for you. Ask instead what is more efficient aso. given a
specific context.
--
PointedEars
|
|
0
|
|
|
|
Reply
|
Thomas
|
7/21/2010 12:24:50 AM
|
|
In article <i243tu$l8g$1@news.xmission.com>,
Kenny McCormack <gazelle@shell.xmission.com> wrote:
>In this group, it is an FGA that one should so:
>
> commandThatGeneratesTheFilenames | while read x ...
>
>instead of the more common:
>
> for i in ...
>
>because of the problems of filenames that spaces and other weird characters.
>
>However, one downside to the "while" method is that inside the loop,
>stdin is now coming from the pipe, and commands that we execute inside
>the loop, that expect a normal stdin, will misbehave.
>
>Workarounds:
> 1) append "< /dev/tty" to each command
> 2) enclose the commands in parens and redirect that. I.e.:
>
> commandThatGeneratesTheFilenames | while read x;do
> (cmd1;cmd2;cmd3;...) < /dev/tty
> done
>
>Method 2 is nice and seems to work fine, but I am wondering if there is
>any hidden cost to it and if there is any more elegant/effcient way to
>do this.
Unless you specifically want to read from the controlling tty rather than
the standard input, it's always better to save the standard input to
another fd and then read from it.
{
commandThatGeneratesTheFilenames |
while read x <&4; do
cmd1
cmd2
cmd3
done 4<&0 0<&3
} 3<&0
In modern shells (ksh93/bash/zsh) you can do:
while read -u3 x; do
cmd1
cmd2
cmd3
done 3< <(commandThatGeneratesTheFilenames)
John
--
John DuBois spcecdt@armory.com KC6QKZ/AE http://www.armory.com/~spcecdt/
|
|
0
|
|
|
|
Reply
|
spcecdt
|
7/21/2010 4:56:01 PM
|
|
In article <B_qdnbdAifw8u9rRnZ2dnUVZ_s6dnZ2d@speakeasy.net>,
John DuBois <spcecdt@armory.com> wrote:
....
> Unless you specifically want to read from the controlling tty rather than
> the standard input, it's always better to save the standard input to
> another fd and then read from it.
>
> {
> commandThatGeneratesTheFilenames |
> while read x <&4; do
> cmd1
> cmd2
> cmd3
> done 4<&0 0<&3
> } 3<&0
What's the difference between enclosing the cmds in {} vs. ()?
--
Faced with the choice between changing one's mind and proving that there is
no need to do so, almost everyone gets busy on the proof.
- John Kenneth Galbraith -
|
|
0
|
|
|
|
Reply
|
gazelle
|
7/21/2010 5:45:28 PM
|
|
On 2010-07-21, Kenny McCormack wrote:
> In article <B_qdnbdAifw8u9rRnZ2dnUVZ_s6dnZ2d@speakeasy.net>,
> John DuBois <spcecdt@armory.com> wrote:
> ...
>> Unless you specifically want to read from the controlling tty rather than
>> the standard input, it's always better to save the standard input to
>> another fd and then read from it.
>>
>> {
>> commandThatGeneratesTheFilenames |
>> while read x <&4; do
>> cmd1
>> cmd2
>> cmd3
>> done 4<&0 0<&3
>> } 3<&0
>
> What's the difference between enclosing the cmds in {} vs. ()?
Commands in ( ) are executed in a subshell.
--
Chris F.A. Johnson, author <http://shell.cfajohnson.com/>
===================================================================
Shell Scripting Recipes: A Problem-Solution Approach (2005, Apress)
Pro Bash Programming: Scripting the GNU/Linux Shell (2009, Apress)
|
|
0
|
|
|
|
Reply
|
Chris
|
7/21/2010 7:05:00 PM
|
|
In article <8aoumsFvcrU2@mid.individual.net>,
Chris F.A. Johnson <cfajohnson@gmail.com> wrote:
>On 2010-07-21, Kenny McCormack wrote:
>> In article <B_qdnbdAifw8u9rRnZ2dnUVZ_s6dnZ2d@speakeasy.net>,
>> John DuBois <spcecdt@armory.com> wrote:
>> ...
>>> Unless you specifically want to read from the controlling tty rather than
>>> the standard input, it's always better to save the standard input to
>>> another fd and then read from it.
>>>
>>> {
>>> commandThatGeneratesTheFilenames |
>>> while read x <&4; do
>>> cmd1
>>> cmd2
>>> cmd3
>>> done 4<&0 0<&3
>>> } 3<&0
>>
>> What's the difference between enclosing the cmds in {} vs. ()?
>
> Commands in ( ) are executed in a subshell.
That's what I thought. So, the answer to the original question, despite
all the other flurry, is simply: Yes, you should use {} rather than ().
--
"We should always be disposed to believe that which appears to us to be
white is really black, if the hierarchy of the church so decides."
- Saint Ignatius Loyola (1491-1556) Founder of the Jesuit Order -
|
|
0
|
|
|
|
Reply
|
gazelle
|
7/21/2010 7:10:05 PM
|
|
Kenny McCormack wrote:
> Chris F.A. Johnson <cfajohnson@gmail.com> wrote:
>> On 2010-07-21, Kenny McCormack wrote:
>>> What's the difference between enclosing the cmds in {} vs. ()?
>> Commands in ( ) are executed in a subshell.
>
> That's what I thought. So, the answer to the original question, despite
> all the other flurry, is simply: Yes, you should use {} rather than ().
No, the answer simply is, again, "it depends." That is the part of software
development that you do not seem to understand.
--
PointedEars
|
|
0
|
|
|
|
Reply
|
Thomas
|
7/21/2010 8:59:14 PM
|
|
On 2010-07-21, John DuBois wrote:
> In article <i243tu$l8g$1@news.xmission.com>,
> Kenny McCormack <gazelle@shell.xmission.com> wrote:
>>In this group, it is an FGA that one should so:
>>
>> commandThatGeneratesTheFilenames | while read x ...
>>
>>instead of the more common:
>>
>> for i in ...
>>
>>because of the problems of filenames that spaces and other weird characters.
>>
>>However, one downside to the "while" method is that inside the loop,
>>stdin is now coming from the pipe, and commands that we execute inside
>>the loop, that expect a normal stdin, will misbehave.
>>
>>Workarounds:
>> 1) append "< /dev/tty" to each command
>> 2) enclose the commands in parens and redirect that. I.e.:
>>
>> commandThatGeneratesTheFilenames | while read x;do
>> (cmd1;cmd2;cmd3;...) < /dev/tty
>> done
>>
>>Method 2 is nice and seems to work fine, but I am wondering if there is
>>any hidden cost to it and if there is any more elegant/effcient way to
>>do this.
>
> Unless you specifically want to read from the controlling tty rather than
> the standard input, it's always better to save the standard input to
> another fd and then read from it.
Why?
> {
> commandThatGeneratesTheFilenames |
> while read x <&4; do
That will fail on filenames beginning or ending with spaces.
while IFS= read -r x <&4
> cmd1
> cmd2
> cmd3
> done 4<&0 0<&3
> } 3<&0
>
> In modern shells (ksh93/bash/zsh) you can do:
>
> while read -u3 x; do
> cmd1
> cmd2
> cmd3
> done 3< <(commandThatGeneratesTheFilenames)
>
> John
--
Chris F.A. Johnson, author <http://shell.cfajohnson.com/>
===================================================================
Shell Scripting Recipes: A Problem-Solution Approach (2005, Apress)
Pro Bash Programming: Scripting the GNU/Linux Shell (2009, Apress)
|
|
0
|
|
|
|
Reply
|
Chris
|
7/21/2010 9:30:36 PM
|
|
In article <4540035.MirdbgypaU@PointedEars.de>,
Thomas 'PointedEars' Lahn <usenet@PointedEars.de> wrote:
>Kenny McCormack wrote:
>
>> Chris F.A. Johnson <cfajohnson@gmail.com> wrote:
>>> On 2010-07-21, Kenny McCormack wrote:
>>>> What's the difference between enclosing the cmds in {} vs. ()?
>>> Commands in ( ) are executed in a subshell.
>>
>> That's what I thought. So, the answer to the original question, despite
>> all the other flurry, is simply: Yes, you should use {} rather than ().
>
>No, the answer simply is, again, "it depends." That is the part of software
>development that you do not seem to understand.
You funny.
(And I've not even seen any pix of you and you funny ears!)
--
> No, I haven't, that's why I'm asking questions. If you won't help me,
> why don't you just go find your lost manhood elsewhere.
CLC in a nutshell.
|
|
0
|
|
|
|
Reply
|
gazelle
|
7/21/2010 9:34:20 PM
|
|
On 2010-07-21, Thomas 'PointedEars' Lahn <PointedEars@web.de> wrote:
> No, the foregone assumption (FGA is not a common Usenet acronym
"Frequently Given Answer", used by some guy whose name I've forgotten
to refer to things he maintains in a format chosen to prevent people from
rebutting the idiocy therein.
-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
|
|
0
|
|
|
|
Reply
|
Seebs
|
7/21/2010 9:49:57 PM
|
|
Kenny McCormack wrote:
> Thomas 'PointedEars' Lahn wrote:
>> Kenny McCormack wrote:
>>> Chris F.A. Johnson <cfajohnson@gmail.com> wrote:
>>>> On 2010-07-21, Kenny McCormack wrote:
>>>>> What's the difference between enclosing the cmds in {} vs. ()?
>>>> Commands in ( ) are executed in a subshell.
>>> That's what I thought. So, the answer to the original question, despite
>>> all the other flurry, is simply: Yes, you should use {} rather than ().
>> No, the answer simply is, again, "it depends." That is the part of
>> software development that you do not seem to understand.
>
> You funny.
It was not my intention to amuse you, but to make you think twice. BTW, in
responding like this you are also making a fool of yourself with regard to
grammar.
> (And I've not even seen any pix of you and you funny ears!)
I have not seen a photo of you either. So what?
--
PointedEars
|
|
0
|
|
|
|
Reply
|
Thomas
|
7/22/2010 12:31:09 AM
|
|
Seebs wrote:
> Thomas 'PointedEars' Lahn wrote:
>> No, the foregone assumption (FGA is not a common Usenet acronym
>
> "Frequently Given Answer", used by some guy whose name I've forgotten
> to refer to things he maintains in a format chosen to prevent people from
> rebutting the idiocy therein.
Thanks. In ten years of regular Usenet participation, in and outside of the
Big 8, I had never come across that acronym. It is not in the Jargon File
either. So I doubt it is more than his original research.
--
PointedEars
|
|
0
|
|
|
|
Reply
|
Thomas
|
7/22/2010 9:44:28 AM
|
|
In article <8ap77sFvcrU3@mid.individual.net>,
Chris F.A. Johnson <cfajohnson@gmail.com> wrote:
>On 2010-07-21, John DuBois wrote:
>> In article <i243tu$l8g$1@news.xmission.com>,
>> Kenny McCormack <gazelle@shell.xmission.com> wrote:
>>>Workarounds:
>>> 1) append "< /dev/tty" to each command
>>> 2) enclose the commands in parens and redirect that. I.e.:
>>>
>>> commandThatGeneratesTheFilenames | while read x;do
>>> (cmd1;cmd2;cmd3;...) < /dev/tty
>>> done
>>>
>>>Method 2 is nice and seems to work fine, but I am wondering if there is
>>>any hidden cost to it and if there is any more elegant/effcient way to
>>>do this.
>>
>> Unless you specifically want to read from the controlling tty rather than
>> the standard input, it's always better to save the standard input to
>> another fd and then read from it.
>
> Why?
Because the standard input may not be the controlling tty (if the program is
piped or redirected into, or started from an environment with no controlling
tty, etc).
John
--
John DuBois spcecdt@armory.com KC6QKZ/AE http://www.armory.com/~spcecdt/
|
|
0
|
|
|
|
Reply
|
spcecdt
|
7/22/2010 3:03:54 PM
|
|
2010-07-20, 12:13(+00), Kenny McCormack:
> In this group, it is an FGA that one should so:
>
> commandThatGeneratesTheFilenames | while read x ...
>
> instead of the more common:
>
> for i in ...
>
> because of the problems of filenames that spaces and other weird characters.
After
IFS='
' # NL
set -f
for i in $(commandThatGeneratesTheFilenames); do...
shouldn't be a problem (except that the loop only starts when
commandThatGeneratesTheFilenames finishes).
Other solution (not any better either than the ones that have
already been given):
while IFS= read <&3 -r i; do
...
done 3<<EOF
$(commandThatGeneratesTheFilenames)
EOF
{
commandThatGeneratesTheFilenames |
while IFS= read <&3 -r i; do
...
done 3<&0 <&4 4<&-
} 4<&0
as already given would be the best one. If you're picky, you may
write it:
{
commandThatGeneratesTheFilenames 4<&- |
while IFS= read <&3 -r i; do
{
...
} 3<&-
done 3<&0 <&4 4<&-
} 4<&0
or:
{
commandThatGeneratesTheFilenames 4<&- |
while IFS= read -r i 4<&-; do
{
...
} <&4 4<&-
done
} 4<&0
--
Stephane
|
|
0
|
|
|
|
Reply
|
Stephane
|
7/26/2010 4:57:51 PM
|
|
|
18 Replies
1393 Views
(page loaded in 0.333 seconds)
|