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 started, 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=""
, 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 -- and keep in mind if your SysAdmin modifies the skel files, the new version does NOT get copied in to your already existing home directory!). 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 .bashrc
or .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 not 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 automatically 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!"
(Also note that you need to source
it: Setting the file to executable (chmod +x ...
) will not do as you expect because it will "execute" in a sub-shell without affecting the parent shell process environment.)
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. (And may even run ou of free environment space memory.)
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".
Another "Edit to add" something to further help: If your goal is to to simply clean up the PATH, you can write a simple utility to do so -- but you have to remember that the utility can only modify it's own copy of PATH. You can work around this by having the utility output (on stdout) the cleaned up path, which the parent process/shell can read to set the new path. For example:
...
export PATH=`/bin/mypathutil --cleanup`
...
I actually have a TCL script, /bin/cleanpath
which outputs a path where every directory is only given once. So something like "/bin:/bin:/usr/bin:/bin:/usr/bin:/usr/games:/bin:/bin" would output simply "/bin:/usr/bin:usr/games". (Technically, my script does slightly more, such as assuring my special custom directory, /usr/local/overrides
, is always first in PATH so I can always put custom command overrides there. This way, I can also temporarily disable some commands by creating symlinks in /usr/local/override that simply point to /bin/true
. (This will probably not work for shell built-ins, however, or programs which use a full pathname to the executable file...)
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.)