Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Lonely spacecowboy

You did not say in what way it fails, nor what <cmd> might be.
But I can say 2 things:

1) pipeing into read only "works" in ksh, the real korn ksh not pdksh or any of the others like bash and zsh that have a "ksh compatibility" mode. But you can still use a similar construct with file redirection that will work. The difference is "|read" creates a child process that read runs in, and any env variables set in that child process are not visible from the parent, and the while-do-done command (and all commands in that loop) ar running in the parent.
The fix is to use "while read ... do ...done < file.txt" instead of "|read"
Also you don't really need to specify a variable for read in this case as there is a built in defaut of $REPLY

while read
     ls -l "$REPLY"
done < files.txt

2) This whole loop only works if NONE of the programs in the loop reads stdin!
The above example using "ls" will work.
Be very careful that your <cmd> does not read stdin, nor any child process it may spawn. Any interactive program is not useable here unless it can be told somehow to operate in a non-interactive mode that ignores stdin. Now that I've said it, maybe you can imagine why given that hint to strart from. If cmd reads stdin, well, the whole time the loop is running, including while <cmd> is running, it's stdin is attached to "<file.txt", which is waiting, trying, that whole time to write more lines from the file. So what happens is you get one successful read command, then some number of bytes or lines gets fed into <cmd>, and the next iteration of read will never get that data. Maybe even the whole rest of the file gets eaten by the first iteration of <cmd> and so you never even get a 2nd iteration of read or the rest of the loop.

You might be able to redirect stdin just for the cmd but I never tried that in a loop like this so I don't know if it actually works.

# test for no tty to allow for cron jobs, cgi script, print filter, etc...
tty -s && MYTTY=`tty` || MYTTY=/dev/null
while read
     vi "$REPLY" <$MYTTY
done < files.txt

or you can just hard code it to always use </dev/null if it never actually needs to be interactive.
while read
     somecommand "$REPLY" </dev/null
done < files.txt

You could also just use awk and not worry about stdin and tty and read etc...
no redirection or piping, no read command, no tty issues, etc...

awk '{system("somecommand \""$0"\"")}' files.txt

It's a little less efficient because system() spawns a new sh process to run command in, where the while-read loop will run command right in the same top level shell process where the while loop itself is running.

Brian K. White    brian@xxxxxxxxx    http://www.myspace.com/KEYofR
filePro  BBx    Linux  SCO  FreeBSD    #callahans  Satriani  Filk!

----- Original Message ----- From: <meino.cramer@xxxxxx>
To: <zsh-users@xxxxxxxxxx>
Sent: Tuesday, March 27, 2007 1:53 PM
Subject: Lonely spacecowboy


I _always_ fail with constructions like

cat file.txt | while read file
    <cmd> "${file}"

when file.txt containing one file per line and
a filename looks like:

   This is an odd filename.txt

. Is there one for all cure for such a constellation?
Too much space gives me headaches ! ;)

Thank you very much for any help in advance! :)

Keep zshing!

Please don't send me any Word- or Powerpoint-Attachments
unless it's absolutely neccessary. - Send simply Text.
See http://www.gnu.org/philosophy/no-word-attachments.html
In a world without fences and walls nobody needs gates and windows.

Messages sorted by: Reverse Date, Date, Thread, Author