Say I have a bash script file config.sh
. It's meant to be source'd by other scripts and variables defined is used as customization of the upper-level scripts.
The problem is, if config.sh
has a temporary variable and its name conflicts with upper-level scripts' variable, it breaks the upper-level one.
config.sh:
TMP1=abc CONFIG_INPUT_DIR="$TMP1"/in CONFIG_OUTPUT_DIR="$TMP1"/out
upper-level script:
TMP1=def source config.sh echo $TMP1
The last echo
prints abc
, not def
.
My current solution is to append a random string to the temporary variable name to make it almost impossible to conflict. e.g:
TMP1_vFc9Uiew=abc CONFIG_INPUT_DIR="$TMP1_vFc9Uiew"/in CONFIG_OUTPUT_DIR="$TMP1_vFc9Uiew"/out unset TMP1_vFc9Uiew
which is painful and makes the code hard to read, in addition not to be perfect.
local
keywordAfter some searching, I've come to know local
keyword. But when I simply declare TMP1
as local
, bash complains that config.sh: line 1: local: can only be used in a function
.
So my another solution is to enclose whole config script as a function:
function config_func_rZ0Yqkpm() { local TMP1=abc CONFIG_INPUT_DIR="$TMP1"/in CONFIG_OUTPUT_DIR="$TMP1"/out } config_func_rZ0Yqkpm unset config_func_rZ0Yqkpm
which is better than previous solution in maintainability and readability, but there's some possibility to conflict as well as solution 1.
I want to know more robust and smart solution without any possibility to conflict.
Thanks.
The easiest way to set environment variables in Bash is to use the “export” keyword followed by the variable name, an equal sign and the value to be assigned to the environment variable.
bash [filename] runs the commands saved in a file. $@ refers to all of a shell script's command-line arguments. $1 , $2 , etc., refer to the first command-line argument, the second command-line argument, etc. Place variables in quotes if the values might have spaces in them.
- 1 means the first parameter passed to the function ( $1 or ${1} ) - # means the index of $1 , which, since $1 is an associative array, makes # the keys of $1. - * means the values of of the # keys in associate array $1.
Variable Scope of Bash FunctionsBy default, every variable has a global scope that means it is visible everywhere in the script. You can also create a variable as a local variable. When you declare a local variable within the function body, it is only visible within that function.
A trick I learned from the keychain
utility is using one program to build a source
-able file containing just the variables that you want to export from your program. You could modify your script to echo
the variables you want to set and then source the output from your program:
$ echo $FOO $ source <(echo FOO=bar) $ echo $FOO bar $
I used echo FOO=bar
to simulate the larger script; your program is probably more involved. The important part is that you must modify your program to output the variables and values you would like to set, rather than just setting them. This lets you decide which variables to expose and which ones to hold private at the cost of another shell process.
You could avoid variables and use functions in config.sh to hold your values:
get_dirname() { echo "abc"; } CONFIG_INPUT_DIR="$(get_dirname)/in" CONFIG_OUTPUT_DIR="$(get_dirname)/out" unset -f get_dirname
If you're still concerned about name collision for functions, this doesn't really help you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With