Awk can't re-create a file it deleted?

awk, unix

Solution

awk is keeping the file open. Try closing it:

echo bla | awk 'BEGIN{fname="foo.txt"} 
{
    print $0 >>fname 
    print "rm -f " fname | "/usr/bin/ksh"
    close("/usr/bin/ksh")
    close( fname ) 
    print $0 >>fname
}'

awk opens the file the first time you write to it, and keeps that file open. When the link is removed from the filesystem, awk still has the file open so it doesn't use the "foo.txt" name to access it. By closing the file, you force awk to look at the filesystem again and create the now non-extant link "foo.txt".

For the benefit of readers who do not understand the distinction between a link and a file, try the following:

$ rm -rf /tmp/foo; mkdir /tmp/foo; cd /tmp/foo  # start with a clean directory
$ touch foo.txt; ln foo.txt bar.txt             # Create a file with two links
$ # run original awk script (without closing the file)
$ cat bar.txt

You will see the line "bla" twice in bar.txt. The reason is that `bar.txt` and `foo.txt` are both links to the same file. `awk` opens that file and writes a line to it, then deletes the link `foo.txt`, then writes another line to the file. When `awk` terminates, the link `foo.txt` has been deleted, but the file is still there and accessible through the link `bar.txt`. If `bar.txt` is deleted, then the filesystem will notice that the link count for the file has dropped to zero and the file will be deleted.

Problem

``` echo bla | awk 'BEGIN{fname="foo.txt"} {print $0 >>fname; print "rm -f " fname | "/usr/bin/ksh"; close("/usr/bin/ksh"); print $0 >>fname}' ``` After this command has executed, I should end up with a file "foo.txt", right ? It doesn't work. I tried system("/usr/bin/rm -f " fname) to remove the file, bash instead of ksh, Linux, HP-UX, Cygwin, fflush(""),... just doesn't work ! It seems after a file is deleted, Awk just can't write to a file with the same name anymore. Looks like a bug in Awk, or am I missing something (big time !) ?!

Original source