Skip to content

Command substitution in an if condition masking return values #1510

@yuya-takeyama

Description

@yuya-takeyama

For new checks and feature suggestions

Here's a snippet or screenshot that shows the problem:

This is a script hiding return value:

#!/bin/bash

set -eu
set -o pipefail

if [ -z "$(ls ./tmp)" ]; then
  echo "./tmp is empty"
else
  echo "./tmp is NOT empty"
fi

echo "script completed"

It doesn't stop the execution even if ./tmp doesn't exist. (unexpected)

$ bash before.sh
ls: ./tmp: No such file or directory
./tmp is empty
script completed

Here's a fixed version:

--- before.sh	2019-03-08 00:28:48.000000000 +0900
+++ after.sh	2019-03-08 00:28:04.000000000 +0900
@@ -3,7 +3,8 @@
 set -eu
 set -o pipefail
 
-if [ -z "$(ls ./tmp)" ]; then
+ls_result=$(ls ./tmp)
+if [ -z "$ls_result" ]; then
   echo "./tmp is empty"
 else
   echo "./tmp is NOT empty"
#!/bin/bash

set -eu
set -o pipefail

ls_result=$(ls ./tmp)
if [ -z "$ls_result" ]; then
  echo "./tmp is empty"
else
  echo "./tmp is NOT empty"
fi

echo "script completed"

It stops at the failure of ls. (expected)

$ bash after.sh
ls: ./tmp: No such file or directory

Here's what shellcheck currently says:

No issues detected!

Here's what I wanted or expected to see:

To be honest, I don't understand the exact reasons that the former script completes running the whole script.
But I think it's helpful if it could detect such a problem.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions