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.

  • Correct perception. The -k allows us to run 30 year old shell scripts without the need to refactor them. Pass temporary environment variables using the prefix syntax instead: var1=x var2=y command ... – Henk Langeveld Apr 24 '14 at 10:06

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.


$ cat cmd1.bash 

echo $VARCMD

Now if I set -k:

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

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 

echo $VARCMD
export | grep VAR

And we ran our above tests again:

$ set -k; ./cmd2.bash VARCMD="hi"; set +k
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 

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
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.


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

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.

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.
| improve this answer | |
  • In this link, ss64.com/bash/set.html, for set -k they have given -o keyword besides the -k option. Does that mean something? – Ramesh Apr 24 '14 at 0:39
  • @Ramesh - set -o keyword is the long form of set -k. See help set | grep -- '-k'. – slm Apr 24 '14 at 0:41
  • ah ok. I was scratching my head for a long time trying to understand why there are 2 options. As usual perfect answer :) – Ramesh Apr 24 '14 at 0:42
  • 4
    ./cmd.bash VARCMD=hi needs set -k to get it to work exactly the way VARCMD=hi ./cmd.bash does without the set -k. Guess the OP's specific question is around the need for bash to support the ./cmd.bash VARCMD=hi form – iruvar Apr 24 '14 at 0:50
  • @1_CR - good point. I believe it has to do with style more than anything, I'll see if I can find an actual source though. – slm Apr 24 '14 at 0:54

Any practical usage of set -k is likely just personal style. Some - perhaps those who like programming languages that offer the ability to use keyword arguments in function calls, or those few people who like the dd command's syntax - may prefer

set -k
command var1=val1 var2=val2


var1=val1 var2=val2 command

The actual reason the option exists in some shells is explained in the rationale for the set command in the POSIX standard:

The following set flags were omitted intentionally with the following rationale:

The -k flag was originally added by the author of the Bourne shell to make it easier
for users of pre-release versions of the shell. In early versions of the Bourne shell
the construct
    set name=value
had to be used to assign values to shell variables.
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.