how make executable script visible to 'which' on osx? - macos

to use lilypond from the command line, you are supposed to make a script, chmod it, and put its location on the PATH (see right-hand column here). you are supposed to use .profile for the PATH change, but that didn't work for me, so i used .bash_profile.
that worked (why didn't .profile work? and should i prefer .bashrc?), but which lilypond doesn't see the script, and i assume the reason is the same reason i can't see it with findExecutable in haskell's System.Directory.
is this so, and how do i fix it?

Bash doesn't expand ~ inside double quotes. Use export PATH=~/bin:"$PATH" instead.
If both ~/.bash_profile and ~/.profile exist, Bash only reads ~/.bash_profile when invoked as an interactive login shell. Terminal and iTerm 2 open new shells as login shells, so Bash reads ~/.bash_profile but not ~/.bashrc. See http://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html.

Related

Bash alias not saving beyond one session?

I'm trying to make a bash alias for traversing through a few folders, but the alias does not save after I close terminal.
I've already saved the alias in the .bashsrc file and have also have run the command . ~/.bashsrc.
Here's what I've done:
sudo nano .bashsrc
Inside bashsrc:
alias x = 'cd Documents/Photos/Family'
And then saved and exit.
. ~/.bashsrc
The alias works in that terminal window, but shows "command not found" if I restart terminal or open a new tab.
You should prefer setting your changes in ~/.bashrc and ~/.bash_profile.
alias x='cd Documents/Photos/Family'
Also, remember aliases won’t be exported to subshells and while using this alias you always need to be present in the directory where Documents is present. I guess your Documents directory is present in home, so it would be better if you do something like:
alias x="cd "$HOME"/Documents/Photos/Family"
Just add this line to the end of both the files and save.
In simple language there are two types of shells for your case, login and non-login interactive shell.
Before starting of a login shell, .bash_profile is sourced and before starting of a non-login shell .bashrc is sourced.
So you should add your changes in both.
If you are on macOS, .bashrc is next to useless for your case. MacOS would treat every shell you open in terminal as a login shell. Although there are some exceptions which i don’t remember.
As mentioned by David in the comments, in some distros ~/.bash_profile is just ~/.profile (e.g. Debian, openSUSE, etc).

How to load ~/.bash_profile when entering bash from within zsh?

I've used bash for two years, and just tried to switch to zsh shell on my OS X via homebrew. And I set my default (login) shell to zsh, and I confirmed it's set properly by seeing that when I launch my Terminal, it's zsh shell that is used in default.
However, when I try to enter bash shell from within zsh, it looks like not loading ~/.bash_profile, since I cannot run my command using aliases, which is defined in my ~/.bash_profile like alias julia="~/juila/julia", etc.. Also, the prompt is not what I set in the file and instead return bash-3.2$.
For some reasons, when I set my login shell to bash, and enter zsh from within bash, then ~/.zshrc is loaded properly.
So why is it not loaded whenever I run bash from within zsh? My ~/.bash_profile is symbolic linked to ~/Dropbox/.bash_profile in order to sync it with my other computers. Maybe does it cause the issue?
Open ~/.zshrc, and at the very bottom of the file, add the following:
if [ -f ~/.bash_profile ]; then
. ~/.bash_profile;
fi
Every time you open the terminal, it will load whatever is defined in ~/.bash_profile (if the file exist). With that, you can keep your custom settings for zsh (colors, and etc). And you get to keep your custom shell settings in .bash_profile file.
This is much cleaner than using bash -l IMO.
If you prefer putting your settings in .bashrc, or .bash_login, or .profile , you can do the same for them.
Similarly, you could also move the common profile settings to separate file, i.e. .my_common_profile, and add the following to both .bash_profile and .zshrc:
if [ -f ~/.my_common_profile ]; then
. ~/.my_common_profile;
fi
An interactive bash reads your ~/.bash_profile if it's a login shell, or your ~/.bashrc if it's not a login shell.
A typical .bash_profile will contain something like:
if [ -f ~/.bashrc ]; then . ~/.bashrc; fi
so .bashrc can contain commands to be executed by either login or non-login shells.
If you run bash -l rather than just bash, it should read your .bash_profile.
Reference: https://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html
For those who have just installed zsh and want their alias from bash to work on zsh do the following
Open .zshrc file in vim like so
vi ~/.zshrc
Scroll to the bottom
click "i" to enable write mode
Tell zsh to load items from bash_profile when needed like so
source ~/.bash_profile
Write and quit like so
:wq
Refresh your zsh like so
source ~/.zshrc
That's it. Now all your saved alias in .bash_profile will be ready to use in zsh.
To complement #Keith Thompson's excellent answer:
macOS:
As #chepner puts it succinctly (emphasis mine):
In OS X, bash is not used as part of the initial [at boot time] login process, and the Terminal.app (or other terminal emulators) process exists outside any pre-existing bash sessions, so each new window [or tab - read: interactive bash shell] (by default) treats itself as a new login session.
As a result, some OSX users only ever create ~/.bash_profile, and never bother with ~/.bashrc, because ALL interactive bash shells are login shells.
Linux:
On Linux, the situation is typically reversed:
bash shells created interactively are [interactive] NON-login shells, so it is ~/.bashrc that matters.
As a result, many Linux users only ever deal with ~/.bashrc.
To maintain bash profiles that work on BOTH platforms, use the technique #Keith Thompson mentions:
Put your definitions (aliases, functions, ...) in ~/.bashrc
Add the following line to ~/.bash_profile
[[ -f ~/.bashrc ]] && . ~/.bashrc
Copy the contents from ~/.bash_profile and paste them at the bottom of ~/.zshrc file.
For ZSH users on MacOs, I ended up with a one liner.
At the very bottom of the ~/.zshrc I added the following line :
bash -l
What it does is simply load the .bash_profile settings(aliases, function, export $PATH, ...)
If you decide to get rid of ZSH and go back to plain BASH, you'll be back to normal with no hassle at all.
If this is something that you do infrequently, or it just isn't appropriate to make changes, you can also 'source' the .bash_profile after launching the child bash shell.
. ~/.bash_profile
This will pull in the settings you make in the .bash_profile script for the life of that shell session. In most cases, you should be able to repeat that command, so it's also an easy way to test any changes that you make without needing to do a full login, as well as bring all of your existing shell sessions up-to-date if you make upgrades to the .bash_profile &/or .bashrc files.
For macOS Big Sur (Version 11.5.2)
Open .zshrc
For example: sudo nano ~/.zshrc
At the end of the file add source ~/.bash_profile
Every time you open the terminal the contents inside the bash profile will be loaded.
Recently I installed oh-my-zsh on OS X and set zsh as default shell and faced the same problem.
I solved this problem by adding source ~/.bash_profile at the end of .zshrc file.
I am using a zsh framework called oh my zsh and I have tried most of the solutions listed here and it broke the format for my custom theme. However, these steps worked for me.
Add new alias(es) at the bottom of my .bash_profile
vi ~/.bash_profile
Make zsh to load items from .bash_profile
source ~/.bash_profile
Refresh zsh
source ~/.zshrc
Restart OSX Terminal app
Try your new alias!
If you'd like to be "profile-centric", you can create .profile as a single source of truth, then load it from both .bash_profile and .zprofile.
.profile
export PATH="/usr/local/opt/python/libexec/bin:$PATH"
# etc., etc.
.bash_profile and .zprofile
if [ -f ~/.profile ]; then
. ~/.profile;
fi
I found this helped bash scripts find the right PATH, etc., and helped me keep configuration in one place.

Terminal: Where is the shell start-up file?

I'm following a tutorial called Starting a Django 1.4 Project the Right Way, which gives directions on how to use virtualenv and virtualenvwrapper, among other things.
There's a section that reads:
If you're using pip to install packages (and I can't see why you wouldn't), you can get both virtualenv and virtualenvwrapper by simply installing the latter.
$ pip install virtualenvwrapper
After it's installed, add the following lines to your shell's start-up file (.zshrc, .bashrc, .profile, etc).
export WORKON_HOME=$HOME/.virtualenvs
export PROJECT_HOME=$HOME/directory-you-do-development-in
source /usr/local/bin/virtualenvwrapper.sh
Reload your start up file (e.g. source .zshrc) and you're ready to go.
I am running Mac OSX, and don't know my way around the Terminal too well. What exactly does the author mean by shell's start-up file (.zshrc, .bashrc, .profile, etc)? Where do I find this file, so that I can add those three lines?
Also, what does he mean by reload your start up file (e.g. source .zshrc)?
I would appreciate a detailed response, specific to OSX.
You're probably using bash so just add these 3 lines to ~/.bash_profile:
$ cat >> ~/.bash_profile
export WORKON_HOME=$HOME/.virtualenvs
export PROJECT_HOME=$HOME/directory-you-do-development-in
source /usr/local/bin/virtualenvwrapper.sh
^D
where ^D means you type Control+D (EOF).
Then either close your terminal window and open a new one, or you can "reload" your .bash_profile like this:
$ source ~/.bash_profile
If you use bash, it usually means ~/.bash_profile.
In Terminal and iTerm new shells are login shells by default, so ~/.bashrc is not read at all. If instructions written for some other platform tell you to add something to .bashrc, you often have to add it to .bash_profile instead.
If both ~/.profile and ~/.bash_profile exist, only .bash_profile is read. .profile is also read by other shells, but many of the things you'd add to .bash_profile wouldn't work with them.
From /usr/share/doc/bash/bash.html:
When bash is invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable.
[...]
When an interactive shell that is not a login shell is started, bash reads and executes commands from ~/.bashrc, if that file exists.
I have Anaconda install, so I add these 3 lines to ~/.bash_profile
export WORKON_HOME=$HOME/.virtualenvs
export PROJECT_HOME=$HOME/Documents/Python
source /Users/Username/anaconda3/bin/virtualenvwrapper.sh
and then reload profile by:
$ source ~/.bash_profile
I use an approach that I think is easy to maintain.
It also works well if you sometimes use Ubuntu systems, however I will be sure to address the OP's OSX requirement in my answer.
Create a .aliases file with your alias(es) in your home directory, e.g. ~/.aliases
Execute this file from your .bashrc file (this is executed each time for a new shell process) with source ~/.aliases. This is all you would actually need to do for Ubuntu btw.
On OSX call .bashrc from your ~/.profile file, i.e. have ~/.bash_profile contain: source ~/.bashrc

source bash script automatically when new shell created

I have bash script within which some function are declared and I like to source it automatically when a new shell created so that I can use the functions immediately. Add a source ~/setsetup.sh in the ~/.bashrc seems do not work.
EDIT:
Both ~/.profile and ~/.bashrc works. I just have a stupid typo when source the script. Thanks!
If the new shell you create is a login shell, it will execute one of .bash_login, .bash_profile, or .profile (whichever it finds first) instead of .bashrc. Typically, you source .bashrc from one of the two bash specific ones if you use them. You should not put any bash-specific commands in .profile, as that file may be read by other non-bash shells. For example, if you decide to source your script from .profile, you should use the . setsetup.sh form, and make sure that nothing bash specific is in that script.
There are several files. The relevant one is likely ~/.profile for your case. It is often used to source .bashrc.
Check man .profile for details. When bash is started as login shell .profile is relevant, otherwise .bashrc.
What you are looking for is ~/.profile which should execute every time you create a new bash shell.

Should aliases go in .bashrc or .bash_profile? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What's the difference between .bashrc, .bash_profile, and .environment?
It seems that if I use
alias ls='ls -F'
inside of .bashrc on Mac OS X, then the newly created shell will not have that alias. I need to type bash again and that alias will be in effect.
And if I log into Linux on the hosting company, the .bashrc file has a comment line that says:
For non-login shell
and the .bash_profile file has a comment that says
for login shell
So where should aliases be written in? How come we separate the login shell and non-login shell?
Some webpage say use .bash_aliases, but it doesn't work on Mac OS X, it seems.
The reason you separate the login and non-login shell is because the .bashrc file is reloaded every time you start a new copy of Bash. The .profile file is loaded only when you either log in or use the appropriate flag to tell Bash to act as a login shell.
Personally,
I put my PATH setup into a .profile file (because I sometimes use other shells);
I put my Bash aliases and functions into my .bashrc file;
I put this
#!/bin/bash
#
# CRM .bash_profile Time-stamp: "2008-12-07 19:42"
#
# echo "Loading ${HOME}/.bash_profile"
source ~/.profile # get my PATH setup
source ~/.bashrc # get my Bash aliases
in my .bash_profile file.
Oh, and the reason you need to type bash again to get the new alias is that Bash loads your .bashrc file when it starts but it doesn't reload it unless you tell it to. You can reload the .bashrc file (and not need a second shell) by typing
source ~/.bashrc
which loads the .bashrc file as if you had typed the commands directly to Bash.
Check out http://mywiki.wooledge.org/DotFiles for an excellent resource on the topic aside from man bash.
Summary:
You only log in once, and that's when ~/.bash_profile or ~/.profile is read and executed. Since everything you run from your login shell inherits the login shell's environment, you should put all your environment variables in there. Like LESS, PATH, MANPATH, LC_*, ... For an example, see: My .profile
Once you log in, you can run several more shells. Imagine logging in, running X, and in X starting a few terminals with bash shells. That means your login shell started X, which inherited your login shell's environment variables, which started your terminals, which started your non-login bash shells. Your environment variables were passed along in the whole chain, so your non-login shells don't need to load them anymore. Non-login shells only execute ~/.bashrc, not /.profile or ~/.bash_profile, for this exact reason, so in there define everything that only applies to bash. That's functions, aliases, bash-only variables like HISTSIZE (this is not an environment variable, don't export it!), shell options with set and shopt, etc. For an example, see: My .bashrc
Now, as part of UNIX peculiarity, a login-shell does NOT execute ~/.bashrc but only ~/.profile or ~/.bash_profile, so you should source that one manually from the latter. You'll see me do that in my ~/.profile too: source ~/.bashrc.
From the bash manpage:
When bash is invoked as an
interactive login shell, or as a
non-interactive shell with the
--login option, it first reads and executes commands from the file
/etc/profile, if that file exists.
After reading that file, it looks for
~/.bash_profile, ~/.bash_login, and
~/.profile, in that order, and reads
and executes commands from the first
one that exists and is readable. The
--noprofile option may be used when the shell is started to inhibit this
behavior.
When a login shell exits, bash
reads and executes commands from the
file ~/.bash_logout, if it exists.
When an interactive shell that is not a login shell is started, bash
reads and executes commands from ~/.bashrc, if that file exists. This
may be inhibited by using the --norc option. The --rcfile file option
will force bash to read and execute commands from file instead of
~/.bashrc.
Thus, if you want to get the same behavior for both login shells and interactive non-login shells, you should put all of your commands in either .bashrc or .bash_profile, and then have the other file source the first one.
.bash_profile is loaded for a "login shell". I am not sure what that would be on OS X, but on Linux that is either X11 or a virtual terminal.
.bashrc is loaded every time you run Bash. That is where you should put stuff you want loaded whenever you open a new Terminal.app window.
I personally put everything in .bashrc so that I don't have to restart the application for changes to take effect.

Resources