9

When adding some directory to $PATH by PATH=~/my_program/bin:”${PATH}”

  1. is it true that only executables directly under the directory will be found via $PATH, but other executables under its subdirectores will not?
  2. is it possible to make all its subdirectories added? Sometimes specify all the subdirectories explicitly can be a lot of work when there are many.

Thanks and regards!

5 Answers 5

5

This script uses tree ...

  • sudo apt-get install tree

You can change the depth of directories by changeing -L 1
and you can choose whether or not to use ~/ ...

UPDATE 2:
.. modified the script to replace only a leading /home/user/ (not "any")
.. and added args..

UPDATE Added check: .. Don't add directory to PATH when it's already in PATH .. This check considers '~/' and '/home/user/' to be different.

Re your question 1... yes it is true; each specific directory must be spedified individually in the PATH..

Re your question 2... Here is a script which will do what you want..
I've tested it, but as it stands it will make the new PATH for the current session..
To make it permanent you can use export PATH (but I'm a bit sketchy on the details of export)

#
# name: path-add-dirs
# eg: $ path-add-dirs "$HOME/bin" "tilde" 1

# When directories are $HOME based, choose format.
# Add directories in tidle format: ~/...
#       ...or as fullly-qualified: /home/user/...

# mode values: "tilde", or  anything else for fully-qualified   
mode="$2" # valid mode values: "tilde", or  anything else   
maindir="$1"; dirs= ; echo
# Buld string of subdirectories to a depth/level of 1  
while IFS= read -r dir ; do
  # Don't add directory if it is already in PATH
  if [[ "$mode" == "tilde" ]] ; then
    # replace only a *leading* :/home/user/ 
    homecheck=":$dir"                    
    dircheck="${homecheck/:$HOME\//:~/}"
    dircheck="${dircheck#:}"
  else
    dircheck="${dir}"
  fi;
  pathcheck=":$PATH:"
  if [[ "$pathcheck" != "${pathcheck/:$dircheck:/}" ]] ; then  
    echo "ALREADY IN PATH: $dircheck"
  else
    dirs="$dirs:$dir"  
    echo " added: $dircheck"
  fi
done < <(tree --noreport -L $3 -fi -d "$maindir")
# Choose one of these two options
if [[ "$mode" == "tilde" ]] 
then PATH="$PATH${dirs//:$HOME\//:~/}" # change :$HOME to :~/ 
else PATH="$PATH$dirs" # this method has fully expanded $HOME
fi
echo
echo "$PATH"
echo
3

It isn't possible, because UNIX-based systems aren't designed to work like that. Typically, all executable files go in one of a small number of directories. For example, all the stuff that I write for my own purposes goes in ~/bin.

If you don't want your actual binaries and scripts to live in a bin directory, you can create a symlink in, e.g., ~/bin to the actual binary.

Having all subdirectories in $PATH isn't particularly desirable, since it just adds more directories to search, increases the risk of other executables getting in your PATH that shouldn't be there, and doesn't really give much of a benefit.

3

This should do the job

PATH="$PATH:$(find ~/bin -type d -printf ":%p")"

Please take into account that

  • The whole directory tree will be traversed, which can take some time, so try to keep the hierarchy small.
  • This won't take into account directories created after the PATH is set.
  • If you invoke this multiple times, there will get a lot of duplicates in the PATH. You might want to assign the original PATH to some temporary variable (eg. OLD_PATH).
1
  • Two bugs: it isn't adding absolute paths -> not working properly. Also, it adds two double colons. Remove : after $PATH.
    – Olli
    Apr 3, 2011 at 10:59
1

No, it is not possible in an easy way. Would it be a possibility to add softlinks to all executables to "~/my_program/bin"?

1

Try it this way:

export PATH="$PATH:$(du "$HOME/.local/bin/" | cut -f2 | tr '\n' ':' | sed 's/:*$//')"

This will add ~/.local/bin itself along with all of 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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .