It turns out there was another exec "chmod" on the path, obscuring my own chmod.
The thing that made this difficult to see was that I'd used the metacharacter "~" in my PATH variable. Only some things will interpret a tilde in the PATH. The which
program does not expand the tilde, so which chmod
told me that /bin/chmod
was the chmod on the path, but bash does expand the tilde, so it tried to run the other chmod (which did nothing.) Meanwhile, sudo
does not expand the tilde so it worked, and gave the impression of a permissions problem.
Resolution: when adding subdirectories of your home directory to your PATH,
use $HOME
instead of ~
.
Option 1: just use /etc/launchd.conf
Add a line like
setenv PATH /Users/username/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
to /etc/launchd.conf
and restart to apply the changes.
The default path is /usr/bin:/bin:/usr/sbin:/sbin
.
/etc/launchd.conf
applies to all processes, which includes graphical applications, non-login shells, and programs started by launchd jobs.
Edit /etc/launchd.conf
manually if you see that some program or installer has added new paths to /etc/paths
or /etc/paths.d/*
.
Option 2: use a launchd job to set the path during startup
Save this plist as /Library/LaunchDaemons/setpath.plist
:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>setpath</string>
<key>ProgramArguments</key>
<array>
<string>bash</string>
<string>-c</string>
<string>launchctl setenv PATH "$((launchctl getenv PATH|tr : \\n
cat /etc/paths /etc/paths.d/*)|awk '!a[$0]++'|paste -sd: -)"</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
The program should be run the next time you restart. It changes the PATH
of the root launchd
process, which is inherited by the user launchd
process.
In my opinion it's easier to just edit /etc/launchd.conf
though.
Option 3: make bash run path_helper even for non-login shells
path_helper is run from /etc/profile
, /etc/zshenv
, and /etc/csh.login
. zsh
reads /etc/zshenv
even for non-login shells but bash
does not read /etc/profile
for non-login shells.
This makes bash
run path_helper
for interactive non-login shells and for non-interactive non-login shells:
echo 'eval $(/usr/libexec/path_helper -s)'>>~/.bashrc
setenv BASH_ENV /etc/profile|sudo tee -a /etc/launchd.conf
It does not make bash
run path_helper
for non-interactive non-login shells invoked as sh
. It also does not affect graphical applications or processes that are not started from shells.
Best Answer
You need to add
/foo/bar
to your$PATH
environment variable. Navigate to your home directory by typingcd
at the prompt, then typenano .profile
. Inside this file, add the following line:then save and quit. Exit Terminal.app (or whichever term program you're using) and restart it.
/foo/bar
should now be in your search path, to make sure typeecho $PATH
and see if it's at the end. You should now be able to runmyfile.py
from anywhere.