Why does the gawk-function close return -1 ?

Hallo,

why does the gawk-function close return -1 ? :confused:
the file sortiert.txt was created and exists (with the sorted print-string).

The source Code:

BEGIN{
	print	"b\n\na\nx\n9" | "sort  > sortiert.txt"
	error = close ("sort > sortiert.txt")
	print error
	if (error) {print "close error"} else {print "close ok"}
}

in this example close returns 0 (as expected):

BEGIN{
print "I am the content" > "foo.txt"
error=	close ("foo.txt")
if (error) {print "close error"} else {print "close ok"}
			}

example 3: close returns 0 (as expected):

BEGIN{
    "date" | getline
    if (!NF) {exit -1;}
    print "Date: ", $0
    error=close("date")
if (error) {print "close error"} else {print "close ok"}
}

You need to close the writing side of the pipe, not the reading side. From the gawk manual:

======
For example, if you open a pipe with this: "sort -r names" | getline foo
then you must close it with this:
close("sort -r names")

hallo,

My example1 is from this nawk-site:

www . staff.science.uu.nl/~oostr102/docs/nawk/nawk_39.html

Trim the spaces in the url (i am not allowed to post links)

print pipes the data to the shell-command.

What output do you get from the following command sequence?:

date
printf "b\n\na\nx\n9\n" | sort > sortiert.txt
printf 'exit code is %d\n' $?
ls -l sortiert.txt
id

Hi,

my cygwin (GNU Awk 4.1.3) output:

wilma@windows10 /
$ unlink sortiert.txt

$ date
Fr, 15. Apr 2016 09:12:41

wilma@windows10 /
$ printf "b\n\na\nx\n9\n" | sort > sortiert.txt

wilma@windows10 /
$ printf 'exit code is %d\n' $?
exit code is 0

wilma@windows10 /
$ ls -l sortiert.txt
-rw----r--+ 1 wilma Kein 9 15. Apr 09:12 sortiert.txt

wilma@windows10 /
$ id
uid=197609(wilma) gid=197121(Kein) Gruppen=197121(Kein),545(Benutzer),4(INTERAKTIV),66049(KONSOLENANMELDUNG),11(Authentifizierte Benutzer),15(Diese Organisation),113(Lokales Konto),66048(LOKAL),262154(NTLM-Authentifizierung),401408(Mittlere Verbindlichkeitsstufe)

wilma@windows10 /
$ more sortiert.txt

9
a
b
x

"sort > sortiert.txt" is not open. The target for your print has two spaces in front of the redirection.

Oh ... :o

thank you

This is fine, because it closes the *writer*. You are closing the *reader*.

Sorry, No. You have to close any file (pipe/redirection/command), be it target for a print or source of a getline , in order to avoid exceeding awk 's open file limit (1021 for my nawk , I guess OPEN_MAX - stdin, stdout, stderr).

Yes, but only the writing end of the pipe, because if you close it, the reading end will close it by itself. At least this is what the example in th gawk docs say.

If you want to explicitly close both ends, you would need two close statements, but I guess the second one (for the right side of the pipe) will fail.

No. An awk pipeline does not work that way.

Suppose that we have a file named 123 that contains:

1
2
3

With that file, and an executable shell script named tester containing:

#!/bin/ksh
awk '
BEGIN {	cmd = "cat 123"
	for(i = 1; i <= 4; i++) {
		if((rc = (cmd | getline)) == 1) {
			print $0 > ("no_input_close" i)
			close("no_input_close" i)
		} else if(rc == 0)
			print "EOF in 1st loop on read " i
		else	print "ERROR in 1st loop on read " i
	}
	close(cmd)
	for(i = 1; i <= 4; i++) {
		if((rc = (cmd | getline)) == 1) {
			close(cmd)
			print $0 > ("with_input_close" i)
			close("with_input_close" i)
		} else if(rc == 0)
			print "EOF in 2nd loop on read " i
		else	print "ERROR in 2nd loop on read " i
	}
}'

Running the script produces the output:

EOF in 1st loop on read 4

and the directory contents are:

-rw-r--r--  1 dwc  staff    6 Apr 15 14:20 123
-rw-r--r--  1 dwc  staff    2 Apr 15 14:48 no_input_close1
-rw-r--r--  1 dwc  staff    2 Apr 15 14:48 no_input_close2
-rw-r--r--  1 dwc  staff    2 Apr 15 14:48 no_input_close3
-rwxr-xr-x  1 dwc  staff  540 Apr 15 14:47 tester
-rw-r--r--  1 dwc  staff    2 Apr 15 14:48 with_input_close1
-rw-r--r--  1 dwc  staff    2 Apr 15 14:48 with_input_close2
-rw-r--r--  1 dwc  staff    2 Apr 15 14:48 with_input_close3
-rw-r--r--  1 dwc  staff    2 Apr 15 14:48 with_input_close4

and the contents of the files produced by the awk program are:

$ for i in *input*
> do      echo "*** $i"
>         cat $i
> done
*** no_input_close1
1
*** no_input_close2
2
*** no_input_close3
3
*** with_input_close1
1
*** with_input_close2
1
*** with_input_close3
1
*** with_input_close4
1
$

If the input file had been closed (as you suggested) when the output files ar closed in the 1st awk for loop, there would be four no_input_closeX instead of three and their contents would be the same as the with_input_closeX files. But, instead we see that even though the output files are closed in the 1st loop, the input command pipeline remains open and each getline in the 1st for loop gets a subsequent input line from the cat command instead of restarting at the 1st line as n the 2nd for loop where both the input and output streams are closed each time through the loop.

The only files that awk automatically closes are input files named as operands that are closed when EOF is reached.

2 Likes