简体   繁体   中英

Set an environment variable within a shell alias

On my system, I've got two versions of Java installed - some programs require Java 7, some require Java 8.

Java 8 is my system default, so when I've been running the Java 7 commands, I've been using:

JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.7.*.jdk/Contents/Home/ \
java_7_program

I want to set an alias so I can instead write

j7 java_7_program

I've defined:

alias j7='JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.7.*.jdk/Contents/Home/'

But then running j7 java -version produces:

java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

The man page (search for "Aliases") states that this is done as a direct substitution. Is there a reason as to why this isn't working?

bash --version prints GNU bash, version 4.3.42(1)-release (x86_64-apple-darwin14.5.0)

A more isolated example (minus the java):

$ alias foo='BAR=baz'
$ type foo
foo is aliased to `BAR=baz'
$ foo echo $BAR
[blank line]

Answering your isolated example:

when you do something like this:

bar=foo my_command

then bar is set in my_command 's environment (and is not seen by the current shell). Hence, when you do:

bar=stuff
bar=foo my_command "$bar"

since the expansion of $bar occurs before my_command is executed , then it's like doing:

bar=foo my_command stuff

since the $bar is expanded before my_command is forked. That explains the [blank line] you obtain in your example:

$ alias foo='BAR=baz'
$ type foo
foo is aliased to `BAR=baz'
$ foo echo $BAR
[blank line]

Just for fun, try these:

$ alias foo=BAR=baz
$ BAR=something
$ foo echo "$BAR"
something

makes sense?

$ alias foo=BAR=baz
$ foo eval 'echo "$BAR"'
baz

this is because BAR is passed in eval 's environment, and then echo "$BAR" is expanded… with the expected value (note the single quotes!).

Similarly,

$ alias foo=BAR=baz
$ foo sh -c 'echo "$BAR"'
baz

The jdk1.7.*.jdk bit is probably the problem. If I put an explicit version in it works fine

You can use /usr/libexec/java_home -v 1.7 to get the latest 1.7 version installed.

So to redo your alias, try:

alias j7='JAVA_HOME=`/usr/libexec/java_home -v 1.7`'

Note the back ticks around the java_home bit which will then execute the command to generate the correct path to set JAVA_HOME to.

Shell aliases could not be used to execute anything before setting environment.

Shell aliases could only hold plain commands, no jocker nor sub commands

For doing things like this, you have to write a wrapper script or at least a function .

sudo cat >/usr/local/bin/j7 <<<eof
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.7.*.jdk/Contents/Home/
java $@
eof
sudo chmod +x /usr/local/bin/j7

or add this function definition to your .bashrc :

j7() {
  export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.7.*.jdk/Contents/Home/
  java $@
}

Real usefull bash wrapper

Something like:

j7 () {
    local JLIBROOT dir
    # JLIBROOT=/usr/lib/jdk
    JLIBROOT=/Library/Java/JavaVirtualMachines
    while read dir && [ "$dir" = "${dir//1.7.}" ] ;do
        :
      done < <(
          /bin/ls -1trd $JLIBROOT/*
    )
    if [ "$dir" != "${dir//1.7.}" ] ;then
          export JAVA_HOME=$dir/Contents/Home
          java $@
      else
          echo "Version 1.7 not found in '$JLIBROOT'."
      fi
}

could work on my Linux desktop...

Using env

You can set environmental with the env utility.

alias foo='env - X=42 perl -E"say \$ENV{X}"'

This sets an alias foo which declares the environmental variable X and initializes it to 42 before executing perl and instructing it to print out the environmental variable X .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM