Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

bash read returns with exit code 1 even though it runs as expected

Tags:

linux

bash

I have this construct to initialize a variable with the contents of a file:

echo "yyy" > xxx
read -r -d '' PAYLOAD <<< $(cat xxx)
echo $?
echo $PAYLOAD

This results in:

1
yyy

Why is read returning 1? This is breaking my script, because I run with set -e.

like image 536
blueFast Avatar asked Nov 11 '16 11:11

blueFast


People also ask

What is exit code 1 in bash?

Exit Code 1 indicates that a container shut down, either because of an application failure or because the image pointed to an invalid file. In a Unix/Linux operating system, when an application terminates with Exit Code 1, the operating system ends the process using Signal 7, known as SIGHUP.

What does [- Z $1 mean in bash?

$1 means an input argument and -z means non-defined or empty. You're testing whether an input argument to the script was defined when running the script.

What is an exit code of 1?

The "Exit Code 1" is simply a "Generic Exit Code" which means the job failed and this can be for any reason.

What is $@ in bash?

bash [filename] runs the commands saved in a file. $@ refers to all of a shell script's command-line arguments. $1 , $2 , etc., refer to the first command-line argument, the second command-line argument, etc. Place variables in quotes if the values might have spaces in them.


2 Answers

read is returning 1 because it returns 0 only when end-of-file is not encountered.

As per help read:

Exit Status:
The return code is zero, unless end-of-file is encountered

You don't even need a read here, just use $(<file) to read the file content into a variable:

echo "yyy" > xxx
payload=$(<xxx)
echo $?
echo "$payload"

It is advisable to not use all uppercase variable names in order to avoid clash with ENV variables.

like image 79
anubhava Avatar answered Oct 02 '22 01:10

anubhava


Actually the correct answer here is that in your case, read fails because it did not encounter a delimiter before EOF.

Because you set the delimiter to be the empty string (-d ''), read will fail to find that and will exit with 1. It will still read everything, but it only does this because it can't find the delimiter. That's why it appears to have worked, but seems to have failed also.

A trick proposed in another answer is to use a while loop/if statement. So something like this

if read -rd '' PAYLOAD; then :; fi <<< $(cat xxx)

Or (shorter)

if read -rd '' PAYLOAD; then :; fi < xxx

Should be enough to prevent the shell from seeing the exit code of the read command.

Sources: https://unix.stackexchange.com/a/265151/44793

like image 24
smac89 Avatar answered Oct 02 '22 01:10

smac89