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?
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