11

I am using bash and most interested in an answer for bash, but you can answer about how to do it in other shells if you want.

I have an environment variable, KEY, and I want to store the value of that environment variable in a a file. Currently I am doing

echo "${KEY}" > ./key.pem

In practice this seems to be OK, but in theory this breaks when KEY=-n.

$ export KEY=-n
$ echo BEGIN "${KEY}" END
BEGIN -n END
$ echo "${KEY}" END
END$

So, is there a better way to store the value of a single environment variable in a file? (Note that export and declare will include the name of the variable in their outputs, which is no good for me.)

9
  • What will use the file? Will it be used to set the value again in a shell script, or by some other tool? Commented Aug 12, 2019 at 17:38
  • 1
    @drewbenn echo -- "$KEY" would not help. It would output -- -n. Commented Aug 12, 2019 at 17:45
  • 1
    @Kusalananda, I'm a bit disappointed that all my shells consistently output -- -n Commented Aug 12, 2019 at 17:53
  • 1
    This is one of the reasons why printf is always better than echo when you don't have complete control over what input you want to print. Commented Aug 12, 2019 at 18:12
  • 1
    @ilkkachu, the rc clone for Unix and its es/akanga derivatives support echo --. Early versions of zsh did as well, but the end-of-option delimiter later changed to - for consistency with Bourne/Korn shell and builtins I suppose. Commented Aug 13, 2019 at 7:22

2 Answers 2

14

If it's storing for the sake of reading it in later (in a bash script), just use declare -p KEY and then source the file to read it in again. If you just want to store the value, use printf '%s\n' "$KEY" as you would do when you output any variable data.

So,

printf '%s\n' "$KEY" >key.pem

or

printf 'BEGIN %s END\n' "$KEY" >key.pem

or whatever you need to output.

Your issue occurs since -n is a valid option to echo in bash. The strings -e and -E (and combinations like -neEne) would also cause issues in bash, for the same reason. Depending on how bash is built or the environment or options, backslash characters in arguments may also be a problem.

These issues and more are outlined in the following Q/A:

10

Many systems have a printenv command that outputs the contents of the given environment variable followed by one newline character to standard output (printenv appeared in 3BSD in the late 70s):

printenv 'My Env Var' > file

Would store the content of the My Env Var variable followed by NL into file in all shells on those systems.

For environment variables that are mapped to shell variables (includes at least those whose name starts with an ASCII letter or underscore and are followed by 0 or more ASCII letters, digits or underscore, and are not otherwise special variables set by the shell), in Bourne-like shells (also works in fish), you can do the same with:

printf '%s\n' "$ENVVAR" > file

(though if the variable is unset, that will still store an empty line into file)

In rc-like shells (where all shell variables are mapped to environment variables):

printf '%s\n' $ENVVAR > file
printf '%s\n' $'My Env Var' > file

(same caveat as above)

In csh-like shells:

printf '%s\n' $ENVVAR:q > file

(if the variable is not set, it will fail and not overwrite file)

Some implementations/versions of ksh don't have printf builtin. In those, you could also do:

print -r -- "$ENVVAR" > file
1
  • printenv is exactly what I needed. printenv VAR > file is far safer than echo "$VAR" > file. Thanks! Commented Jun 28, 2024 at 8:38

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.