gettmpfile - create temporary files

From time to time I wish I could have temporary files in awk: files with unique names that are removed when my script terminates. Of course I could do a

system("/bin/rm " mytmpfiles);

at the end of the script but the problem here is that it must be guaranted that the system() command is run and the files are removed. One possible way is to put the call into an END section:

END {
	system("/bin/rm " mytmpfiles);
	}

could to this. For some reason (and now that I think in more detail about it I'm really not sure why) I don't like this way.

Instead I had the idead of making a shell script that is called from awk and that

  1. creates the files (or better: returns unique filenames), and
  2. removes the files when the awk script terminates.

The script (find it in the download directory) is

  1 #!/bin/sh
  2 #
  3 
  4 #
  5 # gettmpfile -- get one or more temporary files
  6 #
  7 
  8 
  9 cleanup() {
 10 	if [ "$TMPFILES" != "" ]; then
 11 		for i in $TMPFILES; do
 12 			if [ -f $i ]; then
 13 				LIST="$LIST $i"
 14 			fi
 15 		done
 16 
 17 		if [ "$LIST" != "" ]; then
 18 			rm $LIST
 19 		fi
 20 	fi
 21 	}
 22 
 23 __gettmp() {
 24 	let 'count = count + 1'
 25 	tmpfile=$TMPDIR/$prefix-$now-$count
 26 	TMPFILES="$TMPFILES $tmpfile"
 27 	}
 28 
 29 
 30 program=`basename $0`
 31 trapsignals="0 1 2 3 15"
 32 
 33 TMPDIR=/tmp
 34 prefix=tmp
 35 ext=
 36 
 37 options=`getopt de:p:T: $*`  ||  exit 1
 38 set -- $options
 39 while true; do
 40 	opt=$1
 41 	case $opt in
 42 	  -d)
 43 		set -x
 44 		shift
 45 		;;
 46 
 47 	  -e)
 48 	  	ext=$2
 49 		shift 2
 50 		;;
 51 
 52 	  -p)
 53 	  	prefix=$2
 54 		shift 2
 55 		;;
 56 
 57 	  -T)
 58 		TMPDIR=$2
 59 		shift 2
 60 		;;
 61 
 62 	  --)
 63 	  	shift
 64 		break
 65 		;;
 66 
 67 	  -*)
 68 	  	echo $program: unknown option: $opt 1>&2
 69 		exit 1
 70 		;;
 71 
 72 	  *)
 73 		break
 74 		;;
 75 
 76 	esac
 77 done
 78 
 79 
 80 
 81 #
 82 # Check parameters ...
 83 #
 84 
 85 if [ "$#" '!=' 0 ]; then
 86 	echo usage: $program '[<options>]' 1>&2
 87 	exit 1
 88 fi
 89 
 90 
 91 #
 92 # ... capture signals, set some default values ...
 93 #
 94 
 95 trap 'cleanup; exit' $trapsignals
 96 now=`date +'%s'`
 97 pid=`printf '%05d' $PPID`
 98 count=0
 99 
100 #
101 # ... and start.
102 #
103 __gettmp
104 echo $tmpfile
105 
106 
107 #
108 # Create more temporary filenames as required.
109 #
110 
111 while read line; do
112 	__gettmp
113 	echo $tmpfile
114 done
115 
116 exit 0

It's called from awk as a co-process:

cmd = "gettmpfile";
cmd | getline mytempfile;

read the file for the temporary file into the variable mytempfile. After constructing and emitting an initial filename (line #103) the shell script waits for more input (line #111). For every line it gets it returns another name for a temporary file. So in case you have gawk co-processes you can do

cmd = "gettmpfile";
cmd |& getline mytempfile;

printf ("\n") |& cmd;
cmd |& getline myothertempfile;

When the shell script sees that its standard input is closed it terminates; the cleanup() exit handler (line #9) function (set in line #95) removes all temporary files that really exist.

One difference between the shell script and doing it directly in awk might by (I didn't check it) that the shell script removes the temporary files even when it is terminated with one if the usual signal by kill(1); the script catches HUP, INT, QUIT and TERM (see lines #31 and #95).

< dag | at | awk-scripting.de >