MultipleFiles

Last edit

Changed:

< The most portable way is to simply try and read from the file.
< {{{ awk
< function exists(file, dummy, ret)
< {
< ret=0;
< if ( (getline dummy
< file) >=0 )
< {
< # file exists (possibly empty) and can be read
< ret = 1
;
< close(file);
< }
< return ret;
< }
< }}}
< [ I've read reports that earlier versions of mawk would write to stderr
< as well as getline returning <
0 -- is this still true? ]
< On Unix, you can probably use the `test' utility
< {{{ awk
< if (system("test -r " file) == 0)
< # file is readable
< else
< # file is not readable
< }}}

to

> <include "FileExistence">
> [[http://awk.freeshell.org/?action=edit;id=FileExistence| Edit this answer]]

Changed:

< It's automatic (under Unix at least) -- use something like:
< {{{
< awk '/^#
include/ {print $2}' *.c *.h
< }}}

to

> <include "ReadMultipleFiles">
> [[http://awk.freeshell.org/?action=edit;id=ReadMultipleFiles| Edit this answer]]

Changed:

< Use the built-in variable FILENAME:
< {{{
< awk '/^#
include/ {print FILENAME,$2}' *.c *.h
< }}}

to

> <include "FileName">
> [[http://awk.freeshell.org/?action=edit;id=FileName| Edit this answer]]

Changed:

< Use `getline', `close', and `print EXPR > FILENAME', like:
< {{{ awk
< # assumes input file has at least 1 line, output file writeable
< function double(infilename,outfilename, aline)
< {
< while ( (getline aline
< infilename) >0 )
< print(aline aline) > outfilename
;
< close(infilename);
< close(outilename);
< }
< }}}

to

> <include "OpeningFiles">
> [[http://awk.freeshell.org/?action=edit;id=OpeningFiles| Edit this answer]]

Changed:

< Use FILENAME, thusly:
< {{{ awk
< BEGIN { rulesfile="" }
< rulesfile == "" { rulesfile = FILENAME
; }
< FILENAME == rulesfile { build_rule($0); }
< FILENAME != rulesfile { apply_rule($0); }
< }}}
< Example:
< Suppose you have a text-line "database
" and you want to make some
< batch changes to it, by replacing some old lines with new lines.
< {{{ awk
< BEGIN { rulesfile="" }
< rulesfile == "" { rulesfile = FILENAME
; }
< rulesfile == FILENAME { replace[$1] = $0; }
< rulesfile != FILENAME \
< {
< if ($1 in replace)
< print replace[$1];
< else
< print;
< }
< }}}
< Another way, using ARGV:
< {{{
awk
< (FILENAME == ARGV[1]) { replace[$1] = $0; next }
< ($1 in replace) { print replace[$1]; next }
< { print }
< }}}

to

> <include "FirstFile">
> [[http://awk.freeshell.org/?action=edit;id=FirstFile| Edit this answer]]

Changed:

< Use `-v rulesfile=filename' like you would any other variable,
< and then use a `getline' loop (and `close') in your BEGIN
< statement.
< {{{ awk
< BEGIN \
< {
< if (rulesfile=="")
< {
< print "must use -v rulesfile=filename";
< exit(1);
< }
< while ( (getline
< rulesfile) >0 )
< replace[$1]=$0;
< close(rulesfile);
< }
< {
< if ($1 in replace)
< print replace[$1];
< else
< print
;
< }
< }}}

to

> <include "SpecialFile">
> [[http://awk.freeshell.org/?action=edit;id=SpecialFile| Edit this answer]]


Version warning

Some of these techniques will require non-ancient versions of awk.

How can awk test for the existence of a file?

The most portable way to test for the existence of a file is to simply try and read from the file.

        function exists(file,        dummy, ret)
        {
                ret=0;
                if ( (getline dummy < file) >=0 )
                {
                        # file exists (possibly empty) and can be read
                        ret = 1;
                        close(file);
                }
                return ret;
        }

[ I've read reports that earlier versions of mawk would write to stderr as well as getline returning <0 -- is this still true? ]

On Unix, you can probably use the `test' utility

        if (system("test -r " file) == 0)
            # file is readable
        else
            # file is not readable

Edit this answer

How can I get awk to read multiple files?

awk automatically reads multiple files (under Unix at least) -- use something like:

    awk '/^#include/ {print $2}' *.c *.h

Edit this answer

How can I tell from which file my input is coming?

the file name is stored in the built-in variable FILENAME:

    awk '/^#include/ {print FILENAME,$2}' *.c *.h

Edit this answer

How can I get awk to open multiple files (selected at runtime)?

You can open files dynamically using `getline', `close', and `print EXPR > FILENAME', like:

    # assumes input file has at least 1 line, output file writeable
    function double(infilename,outfilename,    aline)
    {
      while ( (getline aline < infilename) >0 )
        print(aline aline) > outfilename;
      close(infilename);
      close(outilename);
    }

Edit this answer

How can I treat the first file specially?

you can tell if awk is parsing the first file given on the command line using FILENAME, thusly:

    BEGIN { rulesfile="" }
    rulesfile == "" { rulesfile = FILENAME; }
    FILENAME == rulesfile { build_rule($0); }
    FILENAME != rulesfile { apply_rule($0); }

Example:

Suppose you have a text-line "database" and you want to make some batch changes to it, by replacing some old lines with new lines.

    BEGIN { rulesfile="" }
    rulesfile == "" { rulesfile = FILENAME; }
    rulesfile == FILENAME { replace[$1] = $0; }
    rulesfile != FILENAME \
    { 
            if ($1 in replace) 
                    print replace[$1];
            else
                    print;
    }

Another way, using ARGV:

    (FILENAME == ARGV[1]) { replace[$1] = $0; next }
    ($1 in replace) { print replace[$1]; next }
    { print }

Edit this answer

How can I explicitly pass in a filename to treat specially?

You can use `-v rulesfile=filename' to process a file differently, like you would any other variable, and then use a `getline' loop (and `close') in your BEGIN statement.

    BEGIN \
    {
      if (rulesfile=="")
      {
        print "must use -v rulesfile=filename";
        exit(1);
      }
      while ( (getline < rulesfile) >0 )
        replace[$1]=$0;
      close(rulesfile);
    }

    {
      if ($1 in replace)
        print replace[$1];
      else
        print;
    }

Edit this answer