Bash – Practical usage of `set -k` option in bash

bashshell

When do we use set -k option in bash?

Bash reference manual says,

All arguments in the form of assignment statements are placed in the environment for a command, not just those that precede the command name.

I understand what the option does, but could not imagine when we need it.

Best Answer

You can basically use it anytime you want to "inject" the environment variables passed into a shell script (as arguments) as if they were set within the environment via export, but without having to have them permanently reside in export's list prior to running commands.

NOTE: There's also the long form of the -k switch, set -o keyword.

Example

$ cat cmd1.bash 
#!/bin/bash

echo $VARCMD

Now if I set -k:

$ set -k; ./cmd1.bash VARCMD="hi"; set +k
hi

But if I just were to run the above script:

$ ./cmd1.bash 

$

What's export doing?

$ help export
...
Marks each NAME for automatic export to the environment of subsequently
executed commands.  If VALUE is supplied, assign VALUE before exporting.
...

So if we were to add export | grep VAR to our script like so:

$ cat cmd2.bash 
#!/bin/bash

echo $VARCMD
export | grep VAR

And we ran our above tests again:

$ set -k; ./cmd2.bash VARCMD="hi"; set +k
hi
declare -x VARCMD="hi"

But without set -k:

$ ./cmd2.bash 

$

So set -k is allowing us to temporarily export variables in mass.

Another example

$ cat cmd3.bash 
#!/bin/bash

echo $VARCMD1
echo $VARCMD2
export | grep VAR

When we set multiple variables they're all exported:

$ set -k; ./cmd3.bash VARCMD1="hi" VARCMD2="bye"; set +k
hi
bye
declare -x VARCMD1="hi"
declare -x VARCMD2="bye"

So then it's just injecting all the environment variables?

No -k is doing a very explicit thing here. It's only exporting variables that were included on the command line when a command was executed.

Example

Say I set this variable:

$ VARCMD1="hi"

Now when we run the same command omitting VARCMD1="hi":

$  set -k; ./cmd3.bash VARCMD2="bye"; set +k

bye
declare -x VARCMD2="bye"

But why does this exist?

I found this source which explains a bit about this feature, titled: "Keyword Parameter Assignment Strings". NOTE: The source URL uses an IP address so I cannot link to it directly here on SE.

http://140.120.7.21/OpenSystem2/SoftwareTools/node16.html

When programming in any language, the variable and its value passing is critical for writing reliable code. Beside the integer and array variable types, all other shell variables accept strings as their values. When talking about shell programming language, to be consistent, we prefer the phrase "keyword parameter". Here are a few points to watch out when assigning values to keyword parameters:

  • To avoid any unexpected effect, always place parameter assignment substring in front of a command string.

    In the B shell, the assigned values of keyword parameters will get stored in (local) shell variables. In bash and ksh, the keyword parameter assignment strings preceding command will not be stored in the shell variables. They only affect the immediate subprocess forked to execute the current command. A line of keyword parameters assignment strings alone does get stored in the (local) shell variables. Keyword parameter assignment strings may also appear as arguments to the alias, declare, typeset, export, readonly, and local builtin commands. [Section 3.4 of Bash Reference Manual]

  • The keyword parameter assignment strings will be treated as arguments for the command to be executed, if they are placed after the command name.

  • The keyword parameters may be manipulated by the set command.
Related Question