I would like to set an environment variable (that we'll call TEST) to store the path to a sub-directory of my home directory : something like /home/myself/dir/. I would like to use the $HOME variable so that the system can get a path that is valid for any user on the system (provided they have a directory called dir in their home folder). I tried several possibilities, but could not get it working. Here is one of my tries:export TEST='$HOME/dir'We can check that the variable has indeed been created :env | grep TESTWhich returns:TEST=$HOME/binSo far so good. However this is where things get tough :cd $TESTReturns:bash: cd: $HOME/bin: No such file or directoryHowever following variant works:eval cd $TESTIs there any way to obtain the same result, but without invoking eval?
setting environment variable as a function of another env variable
environment variables;recursive;home
You can do this, but it requires at least 2 shell variable evaluations, and, normally, all you ever get is one. This is by design - I mean, the shell is where all of your stuff is, so it's best to limit the unexpected to a minimum and avoid opening doors behind doors if you can help it. In any case, you definitely have at your disposal the eval shell built-in: % one=two ; two=three ; eval echo \$$one> three% eval one=\$$two ; echo $one> threeIt does not store a one -> two pointer, but rather it evaluates its arguments as a single shell statement. If that's a little unclear to you, you're not alone. It basically means that the shell runs the same line twice, or at least as near as I can figure it does, and all of the second pass's assignments are affected by the first pass's expansions - which is not normally the case, as you demonstrate in your question. It also means that two's literal value from a certain point in time is stored in one - copied, not linked, so:% one=two ; two=three% eval echo \$$one ; two=four ; eval echo \$$one> three> three% echo $two> fourBut what's up with the backslash? Well, this is where it gets confusing - because you're making two passes you have to quote your quotes. The first pass expands $one to two and strips the first level of quotes, so bye-bye \backslash, but the quoted dollar-sign remains and so $two becomes three on the second pass. This gets really crazy really fast. Shell quotes are hard enough to deal with as it is - just try to quote a single quote. Layer them and you're asking for trouble, strip, evaluate, strip, evaluate and you're going nowhere safe at all - because quotes are there to protect the values of shell parameters and environment variables and the shell from their values.So what you've done is store a literal $ dollar sign within the value of your variable. You didn't store a path to $HOME because the shell did not expand its value during assignment - again, by design. % dir=some_dir ; eval $dir=\$HOME ; echo $some_dir > /your/$HOME/path/You don't have to ask around much about this stuff before you hear of the evil eval. It's commonly called that, and for good reason. Look:two=var\ \;rm\ -f\ /all/your/stuff ; eval home=$two Above home is assigned to the expansion of $two. The home= portion of the statement is evaluated twice - after the first pass and before the second, home briefly equals $two ; but upon the second, after the quotes are stripped, $home expands to var and /all/your/stuff equals 0. That's a super basic quoting example as well, it can go really wrong in a more complicated situation - and just requirement of eval tends to denote complicated.There are other ways to accomplish this - GNOUC notes the ${!bash specific} value inversion assignment (I think that's what it's called...) which probably just does the same thing but in a way that bash has attempted to safeguard. That's a good thing. You could also - and this is probably a good idea - write a function to spit out the values you want when it's called:_home() { exec 2>/dev/null ; set -- /home/*/ ; for h do  (            cd $h && cd $dir && printf %s\\n $dir )         done} ; var=$(_home) ; echo $var> probably...> the...> result...> you...> wanted...Almost as dangerous as eval can be a little imagination in combination with use of the shell's . as well. Because .'s job is to execute commands in the current shell environment rather than subshelling out as do pipes and etc, it's possible to construct a twice-evaluated statement that can affect your environment variables with little fuss.For instance, if you do not quote the limiter on a here-document its contents are subject to shell expansion. If you take that one further and . source it you can execute the results of its expansions. Like this:% . <<HERE /dev/stdin> ${one=two}three=four> home='$HOME'> HERE% [ $home = $HOME ] && echo $twothree> fourSee, in this way, at least, the quotes are easier because they're not stripped except from within an expansion, but they can still get tricky when your expansions do contain quotes. Anyway, that about wraps it up for what I know on the subject.Actually, one more thing, and this is super-duper risky, but it's your computer: % var=eval\ echo\ \$HOME % $var > /YOUR/HOMEBut... % cd eval echo $HOME obviously doesn't work...