Search code examples
bashshelltmp

Why am I getting "not a valid identifier" when trying to read a tmp file in a bash script?


I am using a bash script with some inline python to read a JSON API. I take a small part of the output and dump it into a temporary file. I know that the temporary file exists, because I am able to run a head operation on it. However, when it comes time to actually iterate over the lines in the file, I get an error like read: /tmp/temporary_tag_storage.H9hEH6': not a valid identifier

Here is the full relevant part of my script:

#!/usr/bin/env bash

getTagByNumber () {
    SOMETHING=$(curl -s 'https://localhost:8000/api/tagstubs' | \
        python3 -c "import sys, json; print(json.load(sys.stdin)[$1]['tag'])")
    echo "$SOMETHING" >&3
}

TAGNUMBER=0;
tmpfile=$(mktemp /tmp/temporary_tag_storage.XXXXXX)
# create file descriptor 3 for writing to a temporary file so that
# echo ... >&3 writes to that file
exec 3>"$tmpfile"
# create file descriptor 4 for reading from the same file so that
# the file seek positions for reading and writing can be different
exec 4<"$tmpfile"
while [ $TAGNUMBER -lt 5 ]
do
    getTagByNumber $TAGNUMBER $TAGS
    TAGNUMBER=$(( $TAGNUMBER + 1 ))
done

#This works, dutifully spitting out five lines of text.
head -n $TAGNUMBER <&4

#So why does this give me "not a valid identifier"?
while read $tmpfile; do
  echo "$p"
done
#rm "$tmpfile"

... and here is the output:

politics
sports
religion
film
television
./createtags.sh: line 83: read: `/tmp/temporary_tag_storage.H9hEH6': not a valid identifier

As you can see, the first attempt to read the tags is successful, spitting out a bunch of topic names. That's why I'm so confused about the second while loop failing.

I've tried putting double quotes around $tmpfile variable name in the definition of the second while loop, and that doesn't seem to help.

Anyone know what I'm doing wrong?


Solution

  • Typical use is:

    while read variable_name
    do
        ... some action ...
    done < input_source
    

    In your case variable_name == /tmp/temporary_tag_storage.H9hEH6 which is a nonsensical variable name hence the error message

    Inside your while loop you reference variable $p but never set it. I'm guessing what you really want is something like:

    while read -r p
    do
        echo "$p"
    done < "$tmpfile"
    

    On each pass through the loop variable p contains the contents of a single line from $tmpfile