Linux check if variable is set

What’s a concise way to check that environment variables are set in a Unix shell script?

I’ve got a few Unix shell scripts where I need to check that certain environment variables are set before I start doing stuff, so I do this sort of thing:

if [ -z "$STATE" ]; then echo "Need to set STATE" exit 1 fi if [ -z "$DEST" ]; then echo "Need to set DEST" exit 1 fi 

which is a lot of typing. Is there a more elegant idiom for checking that a set of environment variables is set? EDIT: I should mention that these variables have no meaningful default value — the script should error out if any are unset.

14 Answers 14

Parameter Expansion

The obvious answer is to use one of the special forms of parameter expansion:

Or, better (see section on ‘Position of double quotes’ below):

The first variant (using just ? ) requires STATE to be set, but STATE=»» (an empty string) is OK — not exactly what you want, but the alternative and older notation.

The second variant (using 😕 ) requires DEST to be set and non-empty.

If you supply no message, the shell provides a default message.

The $ construct is portable back to Version 7 UNIX and the Bourne Shell (1978 or thereabouts). The $ construct is slightly more recent: I think it was in System III UNIX circa 1981, but it may have been in PWB UNIX before that. It is therefore in the Korn Shell, and in the POSIX shells, including specifically Bash.

It is usually documented in the shell’s man page in a section called Parameter Expansion. For example, the bash manual says:

Display Error if Null or Unset. If parameter is null or unset, the expansion of word (or a message to that effect if word is not present) is written to the standard error and the shell, if it is not interactive, exits. Otherwise, the value of parameter is substituted.

The Colon Command

I should probably add that the colon command simply has its arguments evaluated and then succeeds. It is the original shell comment notation (before ‘ # ‘ to end of line). For a long time, Bourne shell scripts had a colon as the first character. The C Shell would read a script and use the first character to determine whether it was for the C Shell (a ‘ # ‘ hash) or the Bourne shell (a ‘ : ‘ colon). Then the kernel got in on the act and added support for ‘ #!/path/to/program ‘ and the Bourne shell got ‘ # ‘ comments, and the colon convention went by the wayside. But if you come across a script that starts with a colon, now you will know why.

Position of double quotes

The gist of the discussion is:

… However, when I shellcheck it (with version 0.4.1), I get this message:

In script.sh line 13: : $ ^-- SC2086: Double quote to prevent globbing and word splitting. 

Any advice on what I should do in this case?

Читайте также:  Linux 3d printer software

The short answer is «do as shellcheck suggests»:

To illustrate why, study the following. Note that the : command doesn’t echo its arguments (but the shell does evaluate the arguments). We want to see the arguments, so the code below uses printf «%s\n» in place of : .

$ mkdir junk $ cd junk $ > abc $ > def $ > ghi $ $ x="*" $ printf "%s\n" $ # Careless; not recommended abc def ghi $ unset x $ printf "%s\n" $ # Careless; not recommended bash: x: You must set x $ printf "%s\n" "$" # Careful: should be used bash: x: You must set x $ x="*" $ printf "%s\n" "$" # Careful: should be used * $ printf "%s\n" $ # Not quite careful enough abc def ghi $ x= $ printf "%s\n" $ # Not quite careful enough bash: x: You must set x $ unset x $ printf "%s\n" $ # Not quite careful enough bash: x: You must set x $ 

Note how the value in $x is expanded to first * and then a list of file names when the overall expression is not in double quotes. This is what shellcheck is recommending should be fixed. I have not verified that it doesn’t object to the form where the expression is enclosed in double quotes, but it is a reasonable assumption that it would be OK.

Источник

Bash function to check if a given variable is set

What I’m interested in is how to extract this into a function that can be reused for different variables. The best I’ve been able to do so far is:

is_set() < local test_start='[ ! -z $]' local tester=$test_start$1$test_end eval $tester > 

Making a function to test if a variable is set doesn’t seem like a good idea. You will either be hardcoding the variable you want to check (which makes no sense), using eval not recommended, especially when you cannot be absolutely assured of the variable content, or passing the value of the variable to check as a parameter which takes you back to a [[ -z $1 ]] test to begin with.

There is a subtle distinction here: [[ -z $var ]] returns true if var is either an empty string or unset. [[ -z $ ]] tests strictly for unset.

@DavidC.Rankin I wanted to write a function to make the code self-documenting, since the syntax is pretty cryptic. Given the complications though, I agree with you, and it got me thinking about the difference between documenting the domain logic you’re composing and documenting the workings of the language itself. Since the language is resisting my efforts here, I’ll stick with what’s simplest, and not try to wrap it in a function.

I’m not 100% certain you will get the same results in bash 3, but you can indirectly check a variable using the ! operator isunset() < [[ -z $]];> You can then use if isunset var; then echo var is not set

3 Answers 3

In Bash you can use [[ -v var ]] . There’s no need for a function or convoluted schemes.

 -v varname True if the shell variable varname is set (has been assigned a value). 

The first 2 command sequences prints ok :

[[ -v PATH ]] && echo ok var="" ; [[ -v var ]] && echo ok unset var ; [[ -v var ]] && echo ok 

I’m guessing this was added in a newer version of Bash than what I’m running? I get bash: conditional binary operator expected , but I’m using the version of Bash that came with OSX (3.2.57). I should probably upgrade anyway, but I’m writing this script to help coworkers set up part of their dev environment, so portability is a concern.

Читайте также:  Добавить системную переменную linux

Then a cleaner way like [[ -z $ ]] , as was pointed out earlier, it’s the way to go. Does it work in Bash 3? Running eval in a function for a simple check is ugly and asking for trouble.

Yes, the [[ -z $ ]] approach works in Bash 3. I’ll stick with that. It’s good to know that -v was added though, thanks!

With [[ . ]] , you can simply do this (there is no need for double quotes):

[[ $var ]] && echo "var is set" [[ $var ]] || echo "var is not set or it holds an empty string" 

If you really want a function, then we can write one-liners:

is_empty() < ! [[ $1 ]]; ># check if not set or set to empty string is_not_empty() < [[ $1 ]]; ># check if set to a non-empty string var="apple"; is_not_empty "$var" && echo "var is not empty" # shows "var is not empty" var="" ; is_empty "$var" && echo "var is empty" # shows "var is empty" unset var ; is_empty "$var" && echo "var is empty" # shows "var is empty" var="apple"; is_empty "$var" || echo "var is not empty" # shows "var is not empty" 

Finally, is_unset and is_set could be implemented to treat $1 as the name of the variable:

is_unset() < [[ -z "$" ]]; > # use indirection to inspect variable passed through $1 is unset is_set() < ! [[ -z "$" ]]; > # check if set, even to an empty string unset var; is_unset var && echo "var is unset" # shows "var is unset" var="" ; is_set var && echo "var is set" # shows "var is set" var="OK" ; is_set var && echo "var is set" # shows "var is set" 

Источник

Check if environment variable is set from the command line

I want to know if a particular environment variable is set or not, from the command line. I need to distinguish between it being set to a blank string (or just whitespace) and not set at all, so I’d like to get a definitive True/False or Yes/No, not just printing nothing if it’s not set. I know that in a script, I can use -z , but I’m not sure if/how I can do it directly from the command line. I tried this:

-z is an operator used by the [ / test command, not a testing construct in general. Unlike in Perl, where print -z «file.txt» actually does test if the file is an empty file (it just prints an empty string if not, so not really useful like that).

Читайте также:  Linux ftp удалить файл

2 Answers 2

Use the $VAR+TEXT> form of parameter expansion. $ is empty if VAR is unset and 1 is VAR is set, even if it’s empty. (Whereas $ is empty if VAR is unset or empty, and 1 if VAR is set to a non-empty value.)

if [ -n "$" ]; then echo "\$MY_URDSFDFS is set" else echo "\$MY_URDSFDFS is not set" fi 

This works in any POSIX or Bourne shell, i.e. in all modern and even most ancient dialects of sh.

This does not distinguish between environment variables and shell variables. If you must reject non-exported shell variables, you can do the test in a separate process: sh -c ‘test -n «$»‘ . This is rarely a concern though.

Please note that this is usually a bad idea, because sometimes it’s inconvenient to unset a variable and sometimes it’s inconvenient to set it to an empty string. Usually an empty environment variable should be treated identically to an unset one.

Источник

check if environment variable is already set [duplicate]

I am writing a shell script, where I have to check if environment variable is set, if not set then I have to set it. Is there any way to check in shell script, whether an environment variable is already set or not ?

Actually, this is not a true duplicate of that question: The OP here wants to know whether a variable was set, and if not do something about it, instead of exitting a script. $ is not a valid answer in that case. set | grep -q ‘^V=’ is. This tests for the presence of the variable and works even if the variable was set but to the empty string.

4 Answers 4

The standard solution to conditionally assign a variable (whether in the environment or not) is:

That will set VAR to the value «foo» only if it is unset.
To set VAR to «foo» if VAR is unset or the empty string, use:

To put VAR in the environment, follow up with:

You can also do export VAR=$ or export VAR=$ , but some older shells do not support the syntax of assignment and export in the same line. Also, DRY; using the name on both sides of the = operator is unnecessary repetition. (A second line exporting the variable violates the same principal, but feels better.)

Note that it is very difficult in general to determine if a variable is in the environment. Parsing the output of env will not work. Consider:

export foo=' VAR=var-value' env | grep VAR 

Nor does it work to spawn a subshell and test:

That would indicate the VAR is set in the subshell, which would be an indicator that VAR is in the environment of the current process, but it may simply be that VAR is set in the initialization of the subshell. Functionally, however, the result is the same as if VAR is in the environment. Fortunately, you do not usually care if VAR is in the environment or not. If you need it there, put it there. If you need it out, take it out.

Источник

Оцените статью
Adblock
detector