Bypass a nawk snippet if the input file is empty

I have a script which generates several output files and use these output files during runtime.

Following are the some of the files generated by the script: apple.txt, section_fruit_out.csv, section_fruit_out_lookup.csv, food_lookup.csv, section_fruit_lookup.csv.

I have a code phrase as below:

nawk 'FNR == NR && NF!=0 {x[$1] = $1; next;} {FS=OFS=","} FNR>1{if ($2 in x) {($6 = "apple")} } 1' apple.txt section_fruit_out.csv > section_fruit_out_lookup.csv 
nawk 'BEGIN { FS = OFS = ","; } FNR == NR { x[$1] = $2; next; } { if ($7 in x && $6 == "") { $6 = x[$7]; } else if ($6 == "" && $7 != "") { $6 = "TO_BE_DEFINED" } } 1' food_lookup.csv section_fruit_out_lookup.csv  > section_fruit_lookup.csv

This code phrase mainly handles the expected job. But the script does not work as expected if the apple.txt file is empty (this file is generated by database queries). If the apple.txt file is empty, the output file (section_fruit_out_lookup.csv) of the first nawk section is also generated empty. Since section_fruit_out_lookup.csv is generated empty and it is used by the second nawk command, the second nawk command also generates an empty output file (section_fruit_lookup.csv).

How can I bypass first nawk command if the apple.txt file is empty and make the second nawk command to use section_fruit_out.csv file instead of using the file: section_fruit_out_lookup.csv?

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

Instead of the NR == FNR test to test whether you’re processing the first file, you could do:

awk 'FILENAME == ARGV[1] {...} ...' file1 file2

But that’s a more expensive test, so if file1 is a regular file, you might as well use @Archemar’s approach and not run awk at all if the first file is empty.

In cases (not yours) where file1 and file2 have to be the same file, you can do:

awk 'FILENAME == ARGV[1] {...} ...' file1 ./file1


awk 'FILENAME == "-" {...} ...' - <file1 file1

An even better approach (portable and efficient):

awk '!file1_processed {...} ...' file1 file1_processed=1 file2

If you need that to apply on ./*.txt for instance, you’d do:

set -- ./*.txt
first=$1; shift
awk '!first_processed {...} ...' "$first" first_processed=1 "[email protected]"

A GNU awk-specific approach:

awk 'ARGIND == 1 {...} ...' file1 file2

Solution 2

there is a test function for zero size file.

if test -s apple.txt
    ## apple.txt non empty
    code ...
    ## file empty

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from or, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply