-1

EDIT: I originally assumed this was a scoping issue. I've updated the title to reflect the actual problem.

I've created an MRE below

#!/bin/bash

while getopts a OPTION do case ${OPTION} in a) echo "archive case" ARCHIVE=true ;; ?) echo "error" ;; esac done

if [[ "${ARCHIVE}" -eq true ]] then echo "it's archived" else echo "It's not archived" fi

when I run './script.sh' I get the return value "it's archived", however when I run './script.sh -a' the output shows "archive case" and "It's archived."

Can someone tell me what is happening here? If the case statement is working why is the ARCHIVE variable being created regardless?

Thanks for your help.

Lauro235
  • 101
  • Learn to use the shell debug/trace features, set -vx (and set +vxto turrn off). You can also useset -xandset +x. The-vis "verbose" you'll see the code before any shell processing has happened, including the full text of loops, etc. The-x(expanded?) prepends+to the front of the line and all environment variables, etc are substituted substituted. You will see there, the exact command that the shell has interpeted from your code and is what is being execute. If you have cmd-substitutions (var=$(myCmd) you'll likely see extra+` char for each sub-level . – shellter Jan 20 '24 at 22:39
  • There are numerous ways, but I recommend adding these to your script until you understand what it is providing. 2nd place would be using it on the cmd line just to test something quickly. 3rd In scripts, you can "wrap" a bit of code with set -vx ... set +vx to see how that section is working. Try it! Just remember to delete or use the set + version to turn off the feature. – shellter Jan 20 '24 at 22:48
  • @shellter, set -x is a synonym for set -o xtrace, and "xtrace" is likely short for "execution trace" (it shows the commands the shell executes, after all expansions etc.) – ilkkachu Jan 21 '24 at 13:57
  • @ilkkachu ; Makes sense, Thanks for that ! – shellter Jan 21 '24 at 17:47

1 Answers1

2

The issue here is not scoping - [[ "${ARCHIVE}" -eq true ]] is an arithmetic test, and likely both strings ${ARCHIVE} and true are evaluating arithmetically to zero.

You probably want [[ "${ARCHIVE}" == true ]] instead - although note that the double quoting on the LHS is not strictly necessary, see When is double-quoting necessary?.

See also Conditional Constructs: [[…]].

steeldriver
  • 81,074
  • It is still rendering the echo statement "it's archived". I changed ARCHIVE=true to ARCHIVE="true" and "${ARCHIVE" -eq true to "true".. No luck yet.. – Lauro235 Jan 20 '24 at 22:35
  • @Lauro235 It's the -eq that should be ==. The quotes don't matter in this particular case. – Kusalananda Jan 20 '24 at 22:37
  • They would still get the same result if ARCHIVE is exported in the calling shell (with the value true), so a perfectly correct script should probably set ARCHIVE to some value other than the string true at the start, or unset it completely. – Kusalananda Jan 20 '24 at 22:38
  • Thanks, -eq belongs to the test builtin, is == also part of the same functionality? – Lauro235 Jan 20 '24 at 22:39
  • Can I set ARCHIVE to null for this purpose Kusalananda – Lauro235 Jan 20 '24 at 22:39
  • @Lauro235 Both are operators used for testing, but -eq assumes you're testing integers, or variables with integer values. You can use unset -v ARCHIVE at the start. Or ARCHIVE=false or ARCHIVE=anchovis or whatever. – Kusalananda Jan 20 '24 at 22:40
  • "and likely both strings ${ARCHIVE} and true are evaluating arithmetically to zero" -- in Bash (in particular), in an arithmetic context, the string true evaluates to the value of the variable true, or zero if it's not set. And if the variable ARCHIVE is not set, "${ARCHIVE}" expands to the empty string, which also evaluates to zero in an arithmetic context. Which is still to say that the test is likely to be true, but the underlying reason might not be what one expects (and the results might be surprising if the string there happens to name an existing variable). – ilkkachu Jan 21 '24 at 17:52