Set path for a specific command under OSX - linux

I have libtool command in both path :
/opt/local/libexec/gnubin/libtool
and
/usr/bin/libtool
The current command is recognized under macport which is the first path.
What can I do if I want the command libtool run from /usr/bin/libtool without removing the macport path?

The PATH doesn't make sense in the context of individual commands. It is a list of directories in priority order. If you want one directory to take precedence over another, put it earlier in the path.
However, there is a way to influence resolution order indirectly; create a directory with a high precedence (i.e. put it early in your PATH) and populate it with symlinks to the preferred versions of programs which would otherwise resolve incorrectly.
A natural choice would be /usr/local/bin but on OSX in particular, it has (bewilderingly IMHO) a lower precedence than /usr/bin out of the box. Maybe simply fix that in your own .bash_profile by putting it first. Or create a dedicated directory for this specific purpose and put that first in your path.
Of course, in your personal Bash (or other shell's) profile, you can also simply create a function or alias which causes the PATH to be bypassed entirely. This generally only makes sense for interactive use, though.

Related

How can I find all the versions of a Unix program on a system?

This came up in coursework, and I'm stuck:
Many systems have more than one version of a utility program so that users can choose the one they want. Suggest a command to find all the versions of make on a system. What determines which one a user actually gets? How might a user override the defaults?
How would you do that?
How UNIX finds programs
Unix-like systems store their executable programs in various directories for historical reasons.
The directories that are searched when you want to run a command are stored in an environment variable called $PATH, separated by colons (:). To see its contents, type echo "$PATH" in a terminal window. On my system, that shows (split to avoid a long line)
/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/lib/jvm/default/bin:
/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl
They're searched in that order. If I want to run make, the system will first check /usr/local/sbin/make (which doesn't exist), then /usr/local/bin/make (also non-existant), then /usr/bin/make (which does exist, so it runs that).
How to figure out which one would run
The program which can be used to look through $PATH to figure out what program would be chosen. Running which make on my system produces the output /usr/bin/make.
Conveniently, which has a -a flag to print all executables that match, not just the first one. (I found this by consulting its manual, by running man which.) So which -a java should tell you where all of the versions of java are.
Changing the defaults
If you like, you can change the contents of the $PATH variable, like you can change any environment variable: If I run PATH="$PATH:/home/anko/bin", the next time the system needs to find a program, it will check through all of what $PATH used to be, plus a directory called bin in my home directory if it couldn't find anything else.
I could also prepend the directory, to make it take precedence over anything else, by doing PATH="/home/anko/bin:$PATH".

Change root-path for bash auto-completition (TAB) feature

Can I force BASH to see certain folder (let's call it main_folder) as the root of my file-system? I need BASH to behave this way at least during auto-completion of parameter names and command names, while inside the folder.
Let's say that I have directory tree that looks like this:
/z/y/main_folder/a.txt
/z/y/main_folder/bin/b.txt
/z/y/main_folder/bin/c.txt
/z/y/main_folder/bin/d.sh
Now that I call this custom version of bash, I could simply type:
/> /bi(TAB)/(TAB) /a(TAB)
What would expand to:
/> /bin/d.sh /a.txt
Where d.sh is command to be run and a.txt is it's first parameter. If I was CDed into /bin/ I could do:
/bin/> ./(TAB) (TAB)(TAB)
What would expand the command d.sh, and would give three options for the first parameter (namely: b.txt, c.txt, d.sh).
Few brief additional points:
I do not care if the original root of the file-system is inaccessible or is accessible via hard/soft link.
I do not care if I am able to run any commands that are out of scope for main_folder (I will change the $PATH variable anyway) or any shell builtins.
I do not care what the $PS#, $PWD, etc. variables actually hold.
I do not want to make my own version of BASH (changing source-code). My application should (probably) be started via some script (sh) or program (C/C++/C#) that setups the environment and either continues in interactive mode or runs interactive shell on one of it's last lines.
I want to run this as an unprivileged user. I do not want to allow the user to chroot.
I am not concerned with security, and I am not intending to jail anyone. I simply need BASH to auto-complete.
I would not mind to 'trap' BASH during directory lookups.
I have a feeling that set, compgen, complete and compopt builtins are what I need to utilize, but I do not know how. It does not seem that the examples I have found about these commands show all the features, and man pages are quite chaotic.
Thanks, Kupto :)

Path variable: Find folder path of specific file

On Linux and other Unix-likes, how do I find the path to a specific file that I can use because of the PATH environment variable? For example, if I can use, from the command line:
ls # technically the file name is "ls.exe"
is there a way I can find the path of the ls.exe file explicitly without looking through the PATH variable myself (i.e. maybe have a program search through it but not look myself)?
I understand there are many pitfalls/caveats of doing this, for example a PATH can be a file or even part of a file (I think), plus symlinks, etc. could make it unreliable, but I'm looking for general use cases.
The reason I am asking is I have Windows with msysgit so I have A LOT of folders in my path, and searching every one would be annoying & time-consuming, not to mention harder because of Windows limitations, but I can still presumably use almost anything Linux can use.
$ type ls.exe
ls.exe is /usr/bin/ls.exe

What is PATH on a Mac (UNIX) system?

I'm trying to setup a project, storm from git:
https://github.com/nathanmarz/storm/wiki/Setting-up-development-environment
Download a Storm release , unpack it, and put the unpacked bin/ directory on your PATH
My question is: What does PATH mean? What exactly do they want me to do?
Sometimes I see some /bin/path, $PATH, or echo PATH.
Can someone explain the concept of PATH, so I can setup everything easily in the future without just blindly following the instructions?
PATH is a special environment variable in UNIX (and UNIX-like, e.g. GNU/Linux) systems, which is frequently used and manipulated by the shell (though other things can use it, as well).
There's a somewhat terse explanation on wikipedia, but basically it's used to define where to search for executable files (whether binaries, shell scripts, whatever).
You can find out what your current PATH is set to with a simple shell command:
: $; echo $PATH
(Note: the : $; is meant to represent your shell prompt; it may be something very different for you; just know that whatever your prompt is, that's what I'm representing with that string.)
Depending on your system and prior configuration, the value will vary, but a very simple example of the output might be something like:
/usr/bin:/bin:/usr/local/bin
This is a colon(:)-separated list of directories in which to search for executable files (things like ls, et cetera.) In short, when you try to execute a command from your shell (or from within some other program in certain ways), it will search through each of the directories in this list, in order, looking for an executable file of the name you're provided, and run the first one it finds. So that's the concept, per your question.
From there, what this documentation is telling you to do is to add the directory where you've unpacked the software, and in particular its bin subdirectory, into your $PATH variable. How to do this depends a bit on which shell you're using, but for most (Bourne-compatible) shells, you should be able to do something like this, if you're in the directory where that bin directory is:
: $; PATH="$PATH:$PWD/bin"; export PATH
In just about all but an actual Bourne shell, this can be shortened to:
: $; export PATH="$PATH:$PWD/bin"
(I won't bother explaining for CSH-compatible shells (because: I agree with other advice that you don't use them), but something similar can be done in them, as well, if that happens to be your environment of choice for some reason.)
Presumably, though, you'll want to save this to a shell-specific configuration file (could be ~/.profile, ~/.bashrc, ~/.zshrc... depending on your shell), and without reference to $PWD, but rather to whatever it expanded to. One way you might accomplish this would be to do something like this:
: $; echo "export PATH=\"\$PATH:$PWD/bin\""
and then copy/paste the resulting line into the appropriate configuration file.
Of course you could also generate the appropriate command in other ways, especially if your $PWD isn't currently where that bin directory is.
See also:
An article about $PATH (and more)
a related question on superuser.com

How to programmatically set a permanent environment variable in Linux?

I am writing a little install script for some software. All it does is unpack a target tar, and then i want to permanently set some environment variables - principally the location of the unpacked libs and updating $PATH. Do I need to programmatically edit the .bashrc file, adding the appropriate entries to the end for example, or is there another way? What's standard practice?
Edit: The package includes a number of run scripts (20+) that all use these named environment variables, so I need to set them somehow (the variable names have been chosen such that a collision is extremely unlikely)
LSB-compliant (see spec) practice is to create a shell script in /etc/profile.d/ folder.
Name it after your application (and make sure that the name is unique), make sure that the name ends with .sh (you might want to add scripts for other shells as well) and export the variables you need in the script. All *.sh scripts from that directory are read at user login--the same time /etc/profile is sourced.
Note that this is not enforced by bash; rather, it's an agreement of sorts.
Standard practice is to install into directories already in the path and in the standard library directory, so there is no need to update these variables.
Updating .bashrc is a bit failure-prone, among other things; what if a user uses a different file or shell?
You can also generate and install a script that sets those variables. Users of your package then source that script or copy its contents to their own shell init file.

Resources