1

I have a text file, "invoice.txt" containing a line beginning "Vendor Invoice Number" which contains an order number field of the form RCTI- followed by alphanumeric characters which constitute the order number.

If I enter the command:

awk '/Vendor Invoice No/ {gsub("RCTI-","",$4) ; print $4 ; exit}' /mnt/path/invoice.txt

from the command line or run it from within a script in bash it returns the invoice number eg REA-0130193/2 (we only want the part following RCTI- and this is correct in this case) so, seeking to make this process only operate on new files and not have to operate over the entire number of invoice files at each execution I incorporate it into a new script which includes an inotifywait to operate on only new text files arriving in the directory i.e.

    inotifywait -m /mnt/path -e create -e moved_to |
    while read path action file; do

        i="$path$file"
        echo "$i"
        orderno="$(awk '/Vendor Invoice No/ {gsub("RCTI-","",$4) ; print $4 ; exit}' $i)"
        echo "$orderno">>test.txt
    done

and this works also, producing new order numbers in "test.txt" as text files arrive. HOWEVER, if I run the script containing this command by calling it thus:

~/script.sh& or ~/script.sh &

from within another script, in this case I don't get anything returned which is driving me crazy. Has anyone got any idea why this stops working when it's a script within a script but works properly when run directly - either in a terminal or backgrounded?

To add to my confusion, other awk commands continue to work in the same script.sh, including one of the form:

paidamount="$(awk '/Payment Amt/ {gsub(",","",$11) ; print $11;exit}' $i)"
    echo "$paidamount">>test.txt

Fearing something to do with special characters I made a separate file, orderno.awk containing the following:

#! /usr/bin/awk -f

/Vendor Invoice No/ {gsub("RCTI-","",$4) ; print $4 ; exit}

and calling it via

orderno="$(~/orderno.awk $i)"

in the same script with no change in behavior.

Writing the command as

orderno="$(awk '/Vendor Invoice No/ {gsub(/RCTI-/,"",$4) ; print $4 ; exit}' $i)"

makes no difference that I can discern.

4
  • Can you clarify exactly what you mean by "I don't get anything returned"? Does the echo "$i" print filenames as expected? Does the echo "$orderno">>test.txt add blank lines to test.txt, or nothing, or ... Commented Dec 27, 2020 at 10:33
  • @GordonDavisson Thank you, I added placeholder to the echo command for the nonworking awk command above ie echo "$orderno,placehollder" and ,placeholder was returned in the output file with no space preceding it. The filename is printed as expected.
    – treuben
    Commented Dec 27, 2020 at 10:47
  • 4
    Hmm, is it a race condition, where awk sometimes reads the file after it's created (signaled by inotifywait), but before the "Payment Amt" line gets written into it? You could try listening for close_write events instead of create. Commented Dec 27, 2020 at 11:53
  • @GordonDavisson You sir, are a legend! You have no idea how long I've looked at that and gotten nowhere. Thank you for your help!
    – treuben
    Commented Dec 27, 2020 at 12:14

1 Answer 1

0

So, as Gordon Davisson suggested, changing the inotifywait line to:

inotifywait -m /mnt/path -e close_write | while read path action file; do

fixed the problem as now the entire file exists when awk is applied to it, and not only part of it. There was a "race condition" wherein, with the previous syntax, the text file had been opened for writing but was not complete and only some of the awk commands applied to it worked. Changing the event for inotifywait to close_write from create did the trick.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .