Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass a glob to a shell script via an environment variable while passing ShellCheck

Let's say I have a shell script, test.sh, that is supposed to echo some number of values. I'd like to be able to pass those values in via an environment variable with glob expansion:

$ ls
1.js  2.js  test.sh*

$ FOO="*.js" bash ./test.sh
1.js 2.js

Easy, you say! Just write

#!/bin/bash
echo $FOO

and indeed, this works. But it does not pass ShellCheck, which calls us out for using implicit globbing/expansion (SC2086). (And this is fair; in the original code, the echo line was cp $FOO $BAR, where indeed we didn't want to expand $BAR; this error catches bugs.)

So, in a quest to make this more explicit, I was hoping that maybe the following would work:

#!/bin/bash
array=( $FOO )
echo "${array[@]}"

but no: we end up with SC2206.

Is there a canonical way of doing this kind of thing, which falls within what the ShellCheck authors consider best practices? (Feel free to use the online checker at www.shellcheck.net to test it out.) Is this the wrong approach entirely? It seems unlikely the ShellCheck authors never thought of this use case...

like image 208
Domenic Avatar asked Aug 29 '17 05:08

Domenic


People also ask

How do I pass an environment variable in bash script?

Environment Variables Bash scripts can also be passed with the arguments in the form of environment variables. This can be done in either of the following ways: Specifying the variable value before the script execution command. Exporting the variable and then executing the script.


1 Answers

There doesn't appear to be a safe workaround for ShellCheck's warnings in this case. However, ShellCheck's diagnostics is not universal truth. As you may have noticed, documentation of some of its warnings includes an Exceptions section. For SC2206 it reads:

Exceptions:

If you have already taken care (through setting IFS and set -f) to have word splitting work the way you intend, you can ignore this warning.

Now, ShellCheck provides directives to ignore warnings on a case-by-case basis:

Shellcheck directives allow you to selectively ignore warnings, and takes the form of comments in files:

hexToAscii() {
  # shellcheck disable=SC2059
  printf "\x$1"
}

Supported directives are

  • disable to disable warnings:

    # shellcheck disable=code[,code...]
    statement_where_warning_should_be_disabled
    

    ...

Directives instead of or immediately after the shebang apply to the entire script. Otherwise, they are scoped to the structure that follows it (such as all branches of a case statement, or an entire function).

So you can suppress your warning as follows:

#!/usr/bin/env bash

# The following line is needed so that the shellcheck directive
# below doesn't have global effect
:

# shellcheck disable=SC2206
array=( $FOO )
echo "${array[@]}"
like image 120
Leon Avatar answered Oct 18 '22 03:10

Leon