Using environment variables when adding paths on MacOS - bash

I've found myself with the need to add a new path permanently in all terminal sessions on my Mac. Specifically I want to add the contents of my $GOPATH/bin to my $PATH.
So far I think my options are to either:
Add it to my $HOME/.bash_profile file using export syntax.
Create a file containing the path to add in the /etc/paths.d directory.
I've settled on option 2, because I like the idea of just adding files with one line in whenever I want a new path added permanently.
I have tried adding in a file /etc/profile.d/gopath containing ~/code/go/bin. This works. However, what I'd like to do is evaluate the environment variable, $GOPATH/bin such that if I decide to change my $GOPATH I only have to change the variable. However, that just adds the literal words "$GOPATH/bin" to my path, it doesn't actually add the directory to my path. The $GOPATH bash environment variable is currently set in my ~/.bashrc file.
Some questions:
Why doesn't the $ syntax evaluate in the $PATH or setting of $PATH? Is that not bash?
What comes first, the inclusion of ~/.bashrc, ~/.bash_profile or /etc/profile.d? It is reasonable of me to think that the environment variable would be there when setting the $PATH?
How can I have this environment variable be evaluated and substituted if it is feasible?
Thanks for your help. All my searches don't seem to come up with the above answers.

Related

zsh: command not found: symfony on ubuntu 20 [duplicate]

I'm using zsh terminal, and I'm trying to add a new entry (/home/david/pear/bin) to the PATH variable. I don't see a reference to the PATH variable in my ~/.zshrc file, but doing echo $PATH returns:
/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
So I know that the path variable is being set somewhere. Where is the PATH variable set / modified for the zsh terminal?
Actually, using ZSH allows you to use special mapping of environment variables. So you can simply do:
# append
path+=('/home/david/pear/bin')
# or prepend
path=('/home/david/pear/bin' $path)
# export to sub-processes (make it inherited by child processes)
export PATH
For me that's a very neat feature which can be propagated to other variables.
Example:
typeset -T LD_LIBRARY_PATH ld_library_path :
Here, add this line to .zshrc:
export PATH=/home/david/pear/bin:$PATH
EDIT: This does work, but ony's answer above is better, as it takes advantage of the structured interface ZSH provides for variables like $PATH. This approach is standard for bash, but as far as I know, there is no reason to use it when ZSH provides better alternatives.
You can append to your PATH in a minimal fashion. No need for
parentheses unless you're appending more than one element. It also
usually doesn't need quotes. So the simple, short way to append is:
path+=/some/new/bin/dir
This lower-case syntax is using path as an array, yet also
affects its upper-case partner equivalent, PATH (to which it is
"bound" via typeset).
(Notice that no : is needed/wanted as a separator.)
Common interactive usage
Then the common pattern for testing a new script/executable becomes:
path+=$PWD/.
# or
path+=$PWD/bin
Common config usage
You can sprinkle path settings around your .zshrc (as above) and it will naturally lead to the earlier listed settings taking precedence (though you may occasionally still want to use the "prepend" form path=(/some/new/bin/dir $path)).
Related tidbits
Treating path this way (as an array) also means: no need to do a
rehash to get the newly pathed commands to be found.
Also take a look at vared path as a dynamic way to edit path
(and other things).
You may only be interested in path for this question, but since
we're talking about exports and arrays, note that
arrays generally cannot be exported.
You can even prevent PATH from taking on duplicate entries
(refer to
this
and this):
typeset -U path
PATH pre-populated
The reason your path already has some entries in it is due to your system shell files setting path for you. This is covered in a couple other posts:
Why and where the $PATH env variable is set?
Where is the source of $PATH? I cannot find it in .zshrc
one liner, without opening ~/.zshrc file
echo -n 'export PATH=~/bin:$PATH' >> ~/.zshrc
or
echo -n 'export PATH=$HOME/bin:$PATH' >> ~/.zshrc
To see the effect, do source ~/.zshrc in the same tab or open a new tab
Added path to ~/.zshrc
sudo vi ~/.zshrc
add new path
export PATH="$PATH:[NEW_DIRECTORY]/bin"
Update ~/.zshrc
Save ~/.zshrc
source ~/.zshrc
Check PATH
echo $PATH
OPTION 1: Add this line to ~/.zshrc:
export "PATH=$HOME/pear/bin:$PATH"
After that you need to run source ~/.zshrc in order your changes to take affect OR close this window and open a new one
OPTION 2: execute it inside the terminal console to add this path only to the current terminal window session. When you close the window/session, it will be lost.
If you are on macOS (I'm on Monterey 12.3.1), you may have been pulling your hair like I did metaphorically. These instructions above all worked for me within the terminal session, but I could never get it to persist no matter what I did with export. Moreover, I couldn't find the .zshrc anywhere.
Turns out Apple does it differently. The file you need to edit is etc/paths. You can simply sudo nano /etc/paths and add your path in a new line. Then simply restart terminal and voila.
for me PATH=$PATH:/path/to/file/bin
then export PATH worked.
to check echo $PATH . other solutions are adding the path temporarily.
I'm on Monterey 12.4 and the only way I could change the path was using the helper function. Editing text files in nano did diddly squat
# append
path+=('/foo/bar/yourpath')
# export to sub-processes
export PATH
to verify your new directory has been added correctly, you can use
print -l $path
thanks to the fact that its type is known to be an array
how to append new plugin to zshrc file. I tried the below syntax but it replaced with new one.
sed -i -e 's/plugins=(.*)/plugins=(zsh-syntax-highlighting)/' ~/.zshrc
I want to add git, file, docker etc.
pl give me the corrected syntax.
KSK

How to remove the need of "./" in every shell script in MacOS?

I'm studying shellscript and I know that there is a way to skip "./" when you need to execute a shellscript.
For example: after I made a script like this:
echo "hello world!"
I use the command "chmod +X" to make it executable. But to execute it on my terminal I need to type:
./helloworld.sh
I know that theres is a way to skip this "./" if you're using bash. You go to .bashrc and write in the end of the script "PATH=PATH:."
But since I'm using MacOS, which use zsh, I tried to type "PATH=PATH:." in the end of my .zshrc but this didn't work.
Then I would like to know if there is a way to remove the need of "./" for every shellscript that I need to run.
Thank you people
P.S.: I have brew and ohmyzsh installed in my machine
What's Wrong with Your Code
The reason your example doesn't work is because PATH is a variable, and you need to expand it by prefixing it with the dollar sign to access its value, e.g. PATH=$PATH:. rather than just PATH=PATH:.. However, there are some other considerations too.
Prepending, Appending, and Exporting PATH
It's generally not recommended to treat your current working directory as part of your PATH for security reasons, but you can do it in any Bourne-like shell by prepending or appending . (which means any current working directory) to your PATH. Depending on where you call it and how you've initialized your shell, you may also need to export the PATH variable to your environment.
Some examples include:
# find the named executable in the current working directory first
export PATH=".:$PATH"
# find the named executable in the current working directory
# only if it isn't found elsewhere in your PATH
export PATH="$PATH:."
# append only the working directory you're currently in when you
# update the PATH variable, rather than *any* current working
# directory, to your PATH
export PATH="$PATH:$PWD"
Note that it's also generally a good idea to quote your variables, since spaces or other characters may cause problems when unquoted. For example, PATH=/tmp/foo bar:$PATH will either not work at all or not work as expected. So, wrap it up for safety (with quotes)!
Use Direnv for Project-Based PATH Changes
You might also consider using a utility like direnv that would enable you to add the current working directory to your PATH when you enter known-safe directories, and remove it from the PATH when leaving the directory. This is commonly used for development projects, including shell scripting ones.
For example, you could create the following ~/dev/foo/.envrc file that would only prepend the current working directory when in ~/dev/foo, and remove it again when you move above the current .envrc in your filesystem:
# ~/dev/foo/.envrc
#
# prepend "$HOME/dev/foo:$HOME/dev/foo/bin" to your
# existing PATH when entering your project directory,
# and remove it from your PATH when you exit from the
# project
PATH_add "$PWD/bin"
PATH_add "$PWD"
Because direnv uses whitelisting and ensures that your items are prepended to PATH, it's often a safer and less error-prone way to manage project-specific modifications to your PATH or other environment variables.
Use "$HOME/bin" to Consolidate Scripts
Another option is to create a directory for shell scripts in your home directory, and add that to your PATH. Then, any script placed there will be accessible from anywhere on your filesystem. For example:
# add this line to .profile, .zprofile, .zshrc, or
# whatever login script your particular terminal calls;
# on macOS, this should usually be .zprofile, but YMMV
export PATH="$HOME/bin:$PATH"
# make a ~/bin directory and place your
# executables there
mkdir -p ~/bin
cp helloworld.sh ~/bin/
Assuming the shell scripts in your bin directory already have their executable bit set (e.g. chmod 755 ~/bin/*sh), you can run any shell script in that directory from anywhere on your filesystem.
You need PATH=$PATH:. -- the $ to expand the (old) value of PATH is important.

Where is PATH defined in CentOS?

I started looking into files such as:
/etc/profile
~/.bash_profile
etc.
in order to locate where environment variables were defined. Unfortunately, I couldn't locate the $PATH variable. I am using Bash.
The initial PATH environment variable is inherited from ... whatever launched the shell. For example commands like sudo, sshd, whatever creates your shall after a desktop login.
There also appears to be a PATH that is hardwired into the bash binary for cases where an initial PATH is not inherited. (Look at the output from strings /bin/bash.)
Then various shell initialization scripts get a go at setting or updating PATH. For example, on Ubuntu the PATH variable is updated by /etc/profile.d/apps-bin-path.sh ... which is run by /etc/profile.
You should not worry (or even ask) where PATH is set, since you should not be trusting a random distro to put the right directories in the right sequence.
Instead, you set the PATH you need in your shell's profile. That's it.
As a starting point, POSIX mandates that getconf PATH returns the system's default PATH. If you have a $HOME/bin and there's a /usr/local/bin, then you add them.
Here's what this looks like on my machine:
PATH="$(/usr/bin/getconf PATH)"
PATH="$PATH:/usr/sbin"
PATH="$PATH:/usr/local/bin"
PATH="$PATH:$HOME/bin"
With this setup, it's easy to adapt the sequence. Maybe you don't like the ancient vim in /usr/bin/vi? Compile it yourself and move /usr/local/bin to the front.

Setting TOMCAT_HOME on Terminal. No such file or directory found

export TOMCAT_HOME=”$(/usr/libexec/apache-tomcat-8.0.32)”
-bash: /usr/libexec/apache-tomcat-8.0.32: No such file or directory
Can you guide me please?
The problem is the way the command is expressed:
export TOMCAT_HOME=”$(/usr/libexec/apache-tomcat-8.0.32)”
which is telling the shell to evaluate /usr/libexec/apache-tomcat-8.0.32 (and set TOMCAT_HOME to the result of that evaluation). That is probably a directory, and does not evaluate as an expression. You should do something like this:
export TOMCAT_HOME=/usr/libexec/apache-tomcat-8.0.32
which merely uses the given value /usr/libexec/apache-tomcat-8.0.32 without trying to make the value do something.
The PATH variable is a different case. You might want to add the bin-directory of Tomcat to the path, e.g., by adding
export TOMCAT_HOME=/usr/libexec/apache-tomcat-8.0.32
export PATH=$TOMCAT_HOME/bin:$PATH
at the end of your .profile file (in your home directory). When you start a (bash) shell in OSX, it initializes the PATH variable using the contents of /etc/paths. Your .profile file can add to that. (Other people may use .bashrc or .bash_profile, but you should read the manual page for bash to understand these alternatives).

Export path in .profile on mac

I can't believe there isn't any tutorials about this after googling.
Can someone point me a direction or explain what these lines and variables mean in .profile on mac? How can someone configure them?
export PATH=/opt/local/bin:/opt/local/sbin:$PATH
# Finished adapting your PATH environment variable for use with MacPorts.
#export PATH="/usr/local/bin:/usr/local/sbin:/usr/local/mysql/bin:$PATH"
export PATH=$PATH:/usr/local/mysql/bin
#export PATH="/usr/local/bin:/usr/local/sbin:/usr/local/mysql/bin:$PATH"
#export PATH=/Applications/MAMP/Library/bin:/Applications/MAMP/bin/php5/bin:/Applications/MAMP/htdocs/cake/cake/console:/opt/local/bin:/opt/local/sbin:$PATH
export PATH=/android-sdks/platform-tools:~/android-sdks/tools:$PATH
export PATH=/Users/android-sdks/platform-tools:/Users/android-sdks/tools:$PATH
Any line starting with # is a comment. PATH= sets the value of the PATH variable, $PATH expands to the current value, and the export at the beginning makes the value available to programs that you run from the terminal.
Let's assume that the initial value of PATH is /usr/bin:/bin.
export PATH=/opt/local/bin:/opt/local/sbin:$PATH
Replace $PATH with the previous value of $PATH. So the above sets PATH to
/opt/local/bin:/opt/local/sbin:/usr/bin:/bin
Moving forward,
export PATH=$PATH:/usr/local/mysql/bin
Again, replace $PATH with the previous value:
/opt/local/bin:/opt/local/sbin:/usr/bin:/bin:/usr/local/mysql/bin
After
export PATH=/android-sdks/platform-tools:~/android-sdks/tools:$PATH
we have
/android-sdks/platform-tools:~/android-sdks/tools:/opt/local/bin:/opt/local/sbin:/usr/bin:/bin:/usr/local/mysql/bin
(The ~ is a special token that will be replaced with the path to your home directory, but you should get the picture.)
And finally, after
export PATH=/Users/android-sdks/platform-tools:/Users/android-sdks/tools:$PATH
we get
/Users/android-sdks/platform-tools:/Users/android-sdks/tools:/android-sdks/platform-tools:~/android-sdks/tools:/opt/local/bin:/opt/local/sbin:/usr/bin:/bin:/usr/local/mysql/bin
PATH is used to find commands that you enter on the command line. So if you type foo, the shell will look for the names below, in the order specified:
/Users/android-sdks/platform-tools/foo
/Users/android-sdks/tools/foo
/android-sdks/platform-tools/foo
~/android-sdks/tools/foo
/opt/local/bin/foo
/opt/local/sbin/foo
/usr/bin/foo
/bin/foo
/usr/local/mysql/bin/foo
To see the current value of PATH, run
echo $PATH
Should you add new directories to the beginning of PATH, or to the end? It doesn't always matter, but sometimes it does. It depends on which locations you want the system to check first.
You should add to the beginning if the goal is to search other directories before looking in the default ones. For example, git is a utility used to manage source code. If I wanted to install a newer version of git in ~/git and use that by default, I'd do:
export PATH=~/git/bin:$PATH
This means that ~/git/bin/git would override /opt/local/bin/git.
On the other hand I might prefer to have the administrator install git system-wide. If I want to use my local copy only until the administrator makes it available for everyone, then this makes more sense:
export PATH=$PATH:~/git/bin
In this case ~/git/bin/git would only be used if /opt/local/bin/git didn't already exist since /opt/local/bin is earlier in the path.
A lot of commands won't exist in more than one place. For example you might write my-backup-script and put it on an Apple Time Capsule at /Volumes/Capsule/scripts. It's not likely that there would be a command called my-backup-script in any other location to conflict. So either of the following commands would let you type my-backup-script and run the right script:
export PATH=/Volumes/Capsule/scripts:$PATH
or
export PATH=$PATH:/Volumes/Capsule/scripts
Is one better? My advice would be to do the latter. Remember that system will need to search the directories in $PATH, in order, for every command that it needs to find. Most commands will be on the local system, so it makes the most sense to put slower network storage at the end of the path.
From the man page, export simply sets an environment variable.
The PATH environment variable tells your Mac where to look for commands that you type on the command line, in the order that it should look. It is a list of paths, delimited by a colon.
The value $PATH is the current value of the PATH environment variable.
Thus, a line like
export PATH=/foo:$PATH
prepends /foo to the PATH
and
export PATH=$PATH:/foo
appends /foo to the PATH
Run man
And then answer the question as export
You can see the current PATH value and observe that there are more than one path present.
(mine was /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin)
Observe that : represents end of a single path.
You can retrieve this by using $PATH
Now when you want to add one more path to this list then you need to append current path to new path like /newPath:$PATH or $PATH:/newPath.
And at last for saving it you need to use export PATH=$PATH:/newPath.
Note : This answer is for novice developers.

Resources