dce@Solbourne.COM (David Elliott) (04/25/89)
This is a trick that Dave Hitz (hitz@auspex.com) and I worked out last year: exec 3>temp.$$ 4<temp.$$ rm -f temp.$$ At this point, you can put all the data you want in the temp file by redirecting to fd 3, as in generate_data 1>&3 After this has been done, fd 4 is still a read descriptor pointing at the beginning of the temp file, so you can read the data in the file by redirecting from fd 4, or, if you need to read it multiple time, by dup'ing fd 4 ("exec 5<&4", for example, to copy it to fd 5). When you're finished, there's no need to clean up, since the file was removed before it was even used. Of course, it is possible to kill the program between the time the temp file is created and the time when it is removed, but at worst you'll end up with an empty file. -- David Elliott dce@Solbourne.COM ...!{boulder,nbires,sun}!stan!dce
dce@Solbourne.COM (David Elliott) (04/26/89)
In article <871@marvin.Solbourne.COM> dce@Solbourne.com (David Elliott) writes: > >After this has been done, fd 4 is still a read descriptor >pointing at the beginning of the temp file, so you can >read the data in the file by redirecting from fd 4, or, >if you need to read it multiple time, by dup'ing fd 4 >("exec 5<&4", for example, to copy it to fd 5). Oops. Looks like I screwed up here. You can't do an "exec 5<&4" because 5 and 4 will still point to the same place. Instead, you have to do multiple redirections before the temp file is removed. This is kind of sad, but I don't think you generally need to make more than a couple of passes on the temp file. -- David Elliott dce@Solbourne.COM ...!{boulder,nbires,sun}!stan!dce
leo@philmds.UUCP (Leo de Wit) (04/27/89)
In article <871@marvin.Solbourne.COM> dce@Solbourne.com (David Elliott) writes: | |This is a trick that Dave Hitz (hitz@auspex.com) and I worked |out last year: | | exec 3>temp.$$ 4<temp.$$ | rm -f temp.$$ For C programs this is already a common technique when dealing with temp files: open a file (giving you a descriptor), then unlink it. As long as the file is not closed, it still can be accessed via the descriptor. Perhaps it is not so commonly used in sh scripts. |At this point, you can put all the data you want in the temp |file by redirecting to fd 3, as in | | generate_data 1>&3 | |After this has been done, fd 4 is still a read descriptor |pointing at the beginning of the temp file, so you can |read the data in the file by redirecting from fd 4, or, |if you need to read it multiple time, by dup'ing fd 4 |("exec 5<&4", for example, to copy it to fd 5). This doesn't work, since 5<&4 effectively is dup2(4,5). And although this gives you a new descriptor, it will have only one seek pointer in the file. This means if you read to EOF on 4, you're also on EOF on 5. Example: ----------- Start of sample program ----------- #! /bin/sh exec 3>temp.$$ 4<temp.$$ exec 5<&4 rm -f temp.$$ cat >&3 <<EOT first second third EOT echo From 4: cat <&4 # rewind 5 echo From 5: cat <&5 ----------- End of sample program ------------- ----------- Output of sample program ---------- From 4: first second third From 5: ----------- End of output of sample program --- The shell has no means to rewind that I know of; however, a simple one-liner will do the trick (add error checking of your fancy): ----- rewind.c: main(argc,argv) int argc; char **argv; { lseek(atoi(argv[1]),0L,0); } After uncommenting the '# rewind 5' the output from 5 is the same as that from 4! Leo. P.S. The descriptor '5' is not needed after all; all one has to do is rewind 4 instead of rewind 5, and then reuse descriptor 4.
dce@Solbourne.COM (David Elliott) (04/29/89)
In article <1015@philmds.UUCP> leo@philmds.UUCP (Leo de Wit) writes: >In article <871@marvin.Solbourne.COM> dce@Solbourne.com (David Elliott) writes: >| exec 3>temp.$$ 4<temp.$$ >| rm -f temp.$$ >For C programs this is already a common technique when dealing with >temp files: open a file (giving you a descriptor), then unlink it. As >long as the file is not closed, it still can be accessed via the >descriptor. Perhaps it is not so commonly used in sh scripts. Give this man a cigar! Seriously, I guess I should have pointed out that the trick here was to duplicate the well-known C technique in shell. In my 6 years as a shell programmer, I had never seen this technique applied to the shell (which is why I felt that it was useful to post the idea). In general, shell programmers either trap 0 (exit from shell), trap a whole slew of signals, or just assume that the shell script will exit cleanly. Most people assume that programming in shell is a bad idea because of all the things you can't do. I enjoy finding ways to do things that appear to be impossible to do in sh, if only to say "nyaah" to people who make statements like "you shouldn't program in sh because it isn't a structured programming language" (not that this trick disproves that, but...) -- David Elliott dce@Solbourne.COM ...!{boulder,nbires,sun}!stan!dce
gwc@root.co.uk (Geoff Clare) (05/02/89)
In article <871@marvin.Solbourne.COM> dce@Solbourne.com (David Elliott) writes: > >This is a trick that Dave Hitz (hitz@auspex.com) and I worked >out last year: > > exec 3>temp.$$ 4<temp.$$ > rm -f temp.$$ A neat idea, but unfortunately it suffers from one big problem - those hard-coded file descriptor numbers. Suppose I execute a shell script which uses this trick (although I am unaware of it) and I use file descriptor 3 on the command line for some reason. The result could be disastrous. The idea could be made to work by having the script execute a program which returns two free file descriptor numbers. But is it worth the bother, just to avoid a "trap" statement? A neater solution could be had if there was a predefined shell variable (like $$, $#, etc.) giving the next available file descriptor. Maybe the Korn shell has such a thing? -- Geoff Clare UniSoft Limited, Saunderson House, Hayne Street, London EC1A 9HH gwc@root.co.uk ...!mcvax!ukc!root44!gwc +44-1-315-6600 FAX: +44-1-315-6622
flint@gistdev.UUCP (05/06/89)
If you are going to do this with the Korn shell, I think you're better off using a co-process, something like this: cat |& print -p "This stuff gets written to the co-process." read -p readup # Now ${readup} contains the stuff read back from the co-process. You can also redirect the input and/or output pipes of the co-process to a numbered file descriptor if you want, without having to have a temporary file sitting in the middle to clean up after. The other advantage is that the co-process can be a whole pipeline to filter the stuff you are running through it, as opposed to simply spitting back what it was given (as the cat above would do: any pipeline works in place of the cat.)