It looks like when adding a directory into $PATH, its subdirectories are not added recursively. So can I do that? Or is there a reason why this is not supported?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
The usual unix directory structure has application files sorted into directories by kind: bin for executables, lib for libraries, doc for documentation and so on. That’s when they are installed in separate directories; often applications are grouped into a few directories (hence many systems have just three directories in $PATH: /usr/local/bin, /usr/bin and /bin). It is rare to have both executable files and subdirectories inside a directory, so there’s no demand for including a directory’s subdirectories in $PATH.
What might occasionally be useful is to include all the bin subdirectories of subdirectories of a given directory in $PATH:
for d in /opt/*/bin; do PATH="$PATH:$d"; done
However, this is rarely done. The usual method when executables in non-standard directories are to be in $PATH is to make symbolic links in a directory in the path such as /usr/local/bin. The stow utility (or xstow) can be useful in that regard.
Method 2
Add them recursively using find like so:
PATH=$PATH$( find $HOME/scripts/ -type d -printf ":%p" )
WARNING: As mentioned in the comments to the question this isn’t encouraged as it poses a security risk because there is no guarantee that executable files in the directories added aren’t malicious.
It’s probably a better solution to follow Gilles’ answer and use stow
Method 3
One reason that this is not supported is because the bin/ (and similar) directories use symbolic links to point to the specific directories where actual executables for programs are installed.
So, if your $PATH includes /usr/local/bin (which it most likely does) that folder is full of symbolic links (like ruby) which point to the specific directory where the code to run ruby is found (like ../Cellar/ruby/2.1.3/bin/ruby).
This is why you don’t have to specify each executable’s folder in your $PATH; the symbolic links customarily found in bin/ type directories handle that for you.
Method 4
In zsh, $PATH can be appended as an array. You can use shell globbing to add multiple subdirectories to the $PATH array.
Example:
In .zshrc:
typeset -U PATH path
BINPATH="$HOME/bin"
path+=("$BINPATH" "${BINPATH}"/*/)
export PATH
This will append all subdirectories of $BINPATH to the $PATH array.
Method 5
Try this way:
export PATH="$PATH:$(du "~/scripts/" | cut -f2 | tr 'n' ':' | sed 's/:*$//')"
This will add ~/scripts itself along with all its subdirectories into $PATH
Explanation:
– du will display all the subdirectories info each line
– cut -f2 will extract the second column, i.e., the names of the subdirectories
– tr 'n' ':' will change each link break into a colon. This will join all lines into a single line and the subdirectories are delimited by a colon
– sed 's/:*$//' will remove the last colon
Method 6
The answers didn’t work for me on Mac OS, so I found a way that works:
export PATH=$PATH:$(find $HOME/apps -type d -maxdepth 1 | paste -sd ":" -)
I hope it helps!
Note: this also includes the folder itself.
Method 7
@lucasls way is great and works really well, though that listed way does only work for Mac, it seems. For Linux (At least on Pop_OS 20.10 using zsh) you have to slightly rearrange things in order for it to work.
export PATH=$PATH:$(find $HOME/apps -maxdepth 1 -type d | paste -sd ":" -)
The -maxdepth is a global option and is required to be listed before the -type argument, otherwise, you end up with an error message stating as such.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0