I want to change my PATH variable in zsh.

Problem: I don't understand where in the .zshrc file I have to make modifications.

Normally, I would look for the assignment to the PATH variable and set the values from scratch how I would like them to be (leaving all the systems binaries directories untouched).

The first lines in my .zshrc file are as follows:

# If you come from bash you might have to change your $PATH.
# export PATH=$HOME/bin:/usr/local/bin:$PATH

# Path to your oh-my-zsh installation.
export ZSH="/Users/Sam/oh-my-zsh"

export PATH=$PATH:/Applications/Postgres.app/Contents/Versions/13/bin


My actual PATH variable is:


I want to delete the directory where python3.8 is in, it's redundant.

My questions:

  1. Do I have to change line 2 or line 7 in my .zshrc file?
  2. Line 2 is commented out...is it executed anyway at the start of the terminal?
  3. I have tried to comment out line 7. But the postgres directory still remained in my PATH variable which I don't understand.
  • 1
    Q1. Line 7. Q2. It's commented out, so it won't be executed. Q3. Not sure, or this would be an answer rather than a comment - I suspect that the $PATH variable had the postgres dir appended in the first instance and you'd have to reboot or just edit the env var to remove it. Not sure on that last point though :)
    – Dave
    Jul 31 at 22:14
  • 1
    I would go on to say, regarding Q1, change neither unless you are actually changing the paths added. If you only want to add a new path, add a line after line 7 to add it (export PATH="$PATH:/path/to/add/here")--that way, you can comment it out to temporarily disable it. (You can also do like I do--comment out the original line and create a new line with my corrections. That way, I can see a "history" of changes I have made.)
    – C. M.
    Aug 1 at 3:51
  • 1
    Regarding Q3, What do you mean by "... still remained ..." ? Most edits do not take immediate effect in your current session--you have to source the rc file again and/or restart your shell session.
    – C. M.
    Aug 1 at 3:53
  • 1
    Answering your question in comments: PATH can be defined (and redefined) in many places: The system default files; Your shell's rc files; Any scripts and commands that may be executed during shell startup; Etc. You need not worry too much about redundant paths, either: Most shells simply skip checking a path it has already checked.
    – C. M.
    Aug 1 at 3:59
  • 1
    Regarding the "$HOME/bin", that is because many experienced users do have their own "private/user" ~/bin directory to place their own custom command overrides. The commented entry is simply a part of the "example" .zshrc file as a guide to "newbies". You did not enter it yourself. (And note that it is usually harmless--non-existent paths simply get skipped.)
    – C. M.
    Aug 1 at 8:02

Re-posting from comments in to an answer, but with some extra notes.

First, search the web for introductory guides to working with the Un*x shell (command line) and terminal sessions. Most of them give a lot of information on the most common environment variables, such as PATH. (Some may not give a lot of detail on the many places the PATH variable is set/modified/etc, however.)

Second, understand that environment variables are per instance, meaning, every process gets it's own copy of the variable (from the parent process) when it is stared, and there is no such thing as a "global environment". You can see this if you open two terminal instances, and in one, type export PATH="" in one, clearing the PATH variable, and then in the other terminal, type echo $PATH. You will see that the PATH variable in the second was not affected by the clearing in the first terminal window.

Third, try to avoid asking multiple questions in one question, unless the questions are all very closely related.

I will be jumping back and forth here between the questions asked (since they are very closely related). Also, I often use bash syntax/commands. Different shells might use other forms (such as setvar in tcsh).

Your default .zshrc file is copied from the skeleton (template) files when your user home directory ($HOME) is created (usually when your user record is created). These skeleton files are typically located in places like /etc/skel, and other places may be defined for specific shells, or by your system administrator.

These default/skeleton files often include samples of common usages, sometimes commented out (prefixing it with a "#"), so when you edit them in your user home directory, you can uncomment or edit them however you like or need.

Keep in mind that not all these files get loaded automatically. They only get loaded when you "log in"--Some might only get loaded when you log in via the GUI, while others only get loaded when you log in to a text-mode console. Commonly, different shells use a name such as .<shell>rc", such as .bashrcor.zshrc`--which are often just simply called "rc files"--to define the default configuration when you log in to/start that shell. Note especially that this means any commands or variables set in your rc files are no available if you execute a process from something like a cron job or a GUI launcher that does not load the shell and it's rc file.

Also keep in mind that the shell does not aromatically reload rc files every time you edit them. To "reload" them after editing them, you either need to source .zshrc (or source .bashrc, etc), or close/exit the shell/terminal and log back in. Some shells can force a session reload, you will have to read your shell's man page for how to do that.

When you use the source .zshrc method, you also need to remember that previous settings and values are kept. That means, unless your rc file explicitly clears the PATH variable, it will continue to contain the previous value and add anything added by the rc file--even if a previous load of the rc file already added it. For example, put the following code in a file named "growvar.sh":

export GROWVAR="$GROWVAR:Grow!"
echo "GROWVAR now contains \"$GROWVAR\""

And save it. Then note the following commands and results:

$ source growvar.sh
GROWVAR now contains ":Grow!"
$ source growvar.sh
GROWVAR now contains ":Grow!:Grow!"
$ source growvar.sh
GROWVAR now contains ":Grow!:Grow!:Grow!"

This is usually harmless for the PATH, since most shells skip checking each part of the $PATH it has already checked. They also ignore "empty" paths, such as "::" (which is actually three empty paths separated by ":"s). This is why `export PATH="$PATH:/new/path/here" will still work even if $PATH was not previously set. If you add a lot of long paths to the PATH variable, however, it may grow very large with multiple and redundant paths.

I am certain I am forgetting something... But here is how it all ties together:

Question #1: Change line #7 -- OR.. simply comment it out and add a "corrected" version. This way, in the future, you can immediately see that you changed it, what it was before the change, and what it is after the change. Do the same for commented out "sample" code from the skeleton files. Do not uncomment them: copy the code, adjust it to your liking, and uncomment the copy.

Question #2: As indicated by the above, the "#" makes the line a comment line, which is simply ignored by the shell.

Question #3: Most likely, you expected that either changing the rc file automatically reloaded it (which I explained above it does not do), or if you did reload (via the source command), you expected the PATH to be cleared of it's current value (which I also explained above is not the case). You need to completely restart/reload the shell to get the changes.

Question (from comments) #1: "Where does it get $PATH from?" It depends. Initially, PATH does not even exist. If you try to reference it, as in $PATH, it simply returns an empty string (""). Once you log in to your shell, the shell will automatically source a number of system default files, typically in /etc/default (and other places, your shell's man page will give you detailed specifics of your shell), which set up the PATH variable for further use. That is why most sample PATH settings use export PATH="$PATH:/new/path/here", so they can preserve any previously set paths (or none at all if PATH did not previously exist).

Question (from comments) #2: Regarding the sample line about "$HOME/bin": Many experienced Un*x users have their own $HOME/bin directory to provide custom commands and overrides specific to their login. Thus, the sample configuration line demonstrates this by adding the directory to the PATH. Any non-existent directories in the PATH variable are simply ignored and skipped without error.

Edit to add: Oh, also... In the extreme edge case of $HOME not being defined, it simply gets replaced by an empty string the same way PATH does. So, "$HOME/bin" evaluates to "/bin".

  • Thank you for your accurate problem analysis and detailed answer! This helps me a lot!
    – aurumpurum
    Aug 1 at 16:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.