26

Homebrew requires us to add eval $(/opt/homebrew/bin/brew shellenv) to ~/.zprofile. What does this actually evaluate to and what does this accomplish?

I am a bit new to shell scripting. I know $var is used to refer to a variable named var but that's about it. What is the meaning of putting a path inside of $()? Also is shellenv an argument here and what does it signify?

1
  • Here is the source code for the shellenv command: permalink, latest link (might not work in the future) Commented May 9 at 15:32

2 Answers 2

16

$() is command substitution. It executes the command inside the parentheses and returns the output of that command.

It's often used to get the output of a program into a variable. e.g.

$ month=$(date +%m) $ echo $month 02 

or to use the output of one program as args for another, e.g.

$ printf '%s\n' $(date +%B) February 

(ok, yeah, printf is a contrived example because just running date +%B produces the same output...but it does demonstrate how it works).

The command inside the parentheses may be as simple or as complex as you need, from a single program to a long pipeline of commands. e.g. I often use commands like the following to remove old kernel packages from my Debian system:

apt-get purge $(dlocate -k | grep '6\.0\.0-[245]') 

BTW, you may also see scripts using backticks (`) for this. This is an old, obsolete form of command substitution, supported for legacy reasons but shouldn't be used in new scripts.

When used with eval, it causes your shell to execute the output. In this case, running /opt/homebrew/bin/brew shellenv returns a bunch of text like var=value and eval runs them in your current shell, thus setting those variables to the required values.

From help eval in bash:

eval: eval [arg ...]

Execute arguments as a shell command.

Combine ARGs into a single string, use the result as input to the shell, and execute the resulting commands.

Exit Status: Returns exit status of command or success if command is null.

Try running /opt/homebrew/bin/brew shellenv by itself to see what output it produces.

2
  • 1
    Thank you for the explanation. That was really it. I first tried running /opt/homebrew/bin/brew shellenv with eval $(/opt/homebrew/bin/brew shellenv) still in ~/.zprofile but it gave no output so got a bit confused. Then I removed it and it gave a bunch of export commands which clearly show how it appends brew to $PATH. Thanks for help! Commented Feb 17, 2023 at 2:11
  • 2
    @Osbridge brew shellenv not giving any output at all under some circumstances is explained by brew help shellenv (mentioned in a recent answer here: Command output evaluation not working in Bash script). Commented Feb 17, 2023 at 7:21
9

It exports environment variables needed for brew to work. For example, if I run it without eval then this is what it outputs in fish shell:

$ /opt/homebrew/bin/brew shellenv set -gx HOMEBREW_PREFIX "/opt/homebrew"; set -gx HOMEBREW_CELLAR "/opt/homebrew/Cellar"; set -gx HOMEBREW_REPOSITORY "/opt/homebrew"; set -q PATH; or set PATH ''; set -gx PATH "/opt/homebrew/bin" "/opt/homebrew/sbin" $PATH; set -q MANPATH; or set MANPATH ''; set -gx MANPATH "/opt/homebrew/share/man" $MANPATH; set -q INFOPATH; or set INFOPATH ''; set -gx INFOPATH "/opt/homebrew/share/info" $INFOPATH; 

Then eval actually executes those set commands.

Important to note that this outputs nothing if it has already been loaded into the session.

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.