You should use /dev/stderr
or /dev/fd/2
instead of /proc/self/fd/2
. gawk
handles /dev/fd/x
and /dev/stderr
by itself (regardless of whether the system has those files or not).
When you do a:
print "x" > "/dev/fd/2"
gawk
does a write(2, "x\n")
, while when you do:
print "x" > "/proc/self/fd/2"
since it doesn't treat /proc/self/fd/x
specially, it does a:
fd = open("/proc/self/fd/2", O_WRONLY|O_CREAT|O_TRUNC);
write(fd, "x\n");
First /proc/self/fd
is Linux specific and on Linux they are problematic. The two versions above are not equivalent when stderr is to a regular or other seekable file or to a socket (for which the latter would fail) (not to mention that it wastes a file descriptor).
That being said, if you need to write to the original stdout, you need to save it away in another fd like:
gawk -i inplace '{
print "goes into the-file"
print "to stdout" > "/dev/fd/3"}' the-file 3>&1
gawk
does redirect stdout with in-place to the file. It's needed because for instance, you'd want:
awk -i inplace '{system("uname")}' file
to store the uname
output into the file
.
find -type f -name 'myfiles' -exec grep -q 'pattern' {} \; -print -exec gawk -i inplace '{do_your_sub_and_print_to_dev/stderr_too}' {} \;
that way you will only use awk to edit the files that actually contain lines matching that pattern.grep
can be. My first instinct is to avoid having to "process" the file twice, but I wouldn't be at all surprised if it is indeed faster nonetheless. It just goes to show why I can trust my gut on profiling tasks-print -exec gawk
is not executed anymore) and 2) it will stop at 1st match so unless the 1st match is on the last line you're still not processing the whole file twice (it's more like 1.X times) . Also, ifgawk -i inplace
works likesed -i
it will edit the file in-place anyway - i.e. updating timestamps, inode etc even if there was nothing to edit...