Specify the command file location from two - linux

I have two command files with same and both of them are located in PATH folder.
This means that which mycmd returns two different path like
$ which mycmd
/usr/local/bin/mycmd
/usr/bin/mycmd
How can I specify mycmd uses /usr/local/bin/mycmd(or the other)?
Any help will be appreciated!

If you feel reluctant to change your path, you can use an alias.
alias mycmd='/usr/local/bin/mycmd'
This is particularly useful if different commands would otherwise require differently ordered paths.
Add the statement to .bashrc, to prevent you from having to type it in at every shell session.

I think that file in directory that is earlier in you PATH will take precedence.
So if your path looks like this:
$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/opt/bin:/usr/games/bin
then /usr/local/bin/mycmd will match before /usr/bin/mycmd and will be the one executed. If you want it the other way around, swap the order in your $PATH.

Related

Should PATH contain directories or full paths to binaries?

I am trying to set up a correct PATH, but I'm wondering what it should contain. If I have
/usr/bin/ls
/usr/local/bin/ls
and I want to prefer the one in /usr/local/bin, which of the following should I use?
PATH=/usr/local/bin/ls:/usr/bin/ls
PATH=/usr/local/bin:/usr/bin
or something else entirely?
This is not per se a suitable question for Stack Overflow.
I expect this to be closed as General Computing or Too Broad;
but the answer is frequently needed by beginners, so I hope this won't be deleted.
PATH works only with directories, not with single files
From the POSIX standard (emphasis mine)
PATH
This variable shall represent the sequence of path prefixes that certain functions and utilities apply in searching for an executable file known only by a filename. The prefixes shall be separated by a colon ( ':' ). [...] The list shall be searched from beginning to end, applying the filename to each prefix, until an executable file with the specified name and appropriate execution permissions is found.
When you type in ls into your shell and your PATH is set to /usr/local/bin/ls:/usr/bin/ls then your shell will …
… look for an executable with the path /usr/local/bin/ls/ls (note the double ls at the end).
As that path does not exist on your system your shell will proceed to look for an executable with the path /usr/bin/ls/ls (double ls again). That path also doesn't exist.
The shell couldn't find an executable using all paths in PATH so your shell will print something like bash: ls: command not found.
So, what did we learn? Paths listed by PATH have to be directories. You cannot list single files. Therefore the correct answer in your case is PATH=/usr/local/bin:/usr/bin.
Where things get interesting
Imagine the following situation. You have two versions of program c1 and two versions of program c2. The different versions are stored in the directories /a/ and /b/.
/a/c1
/a/c2
/b/c1
/b/c2
How can we set PATH to prefer /a/c1 over /b/c1/ but at the same time /b/c2 over /a/c2?
Sadly, there is no way to achieve this directly as we can only specify directories in PATH. We have to move/rename some files or create symlinks and use the symlinks inside the paths. One possible solution:
mkdir /c
ln -s /a/c1 /c/c1
ln -s /b/c2 /c/c2
export PATH=/c:/a:/b
The trailing :/a:/b is not really necessary here. I included them under the assumption that /a and /b contain more executables than just c1 and c2.
Indeed, as you can easily find out through experimentation, the variable PATH should already contain a list of directories which are consulted in that order. In fact, you should already find that you have /usr/local/bin and /usr/bin in the default PATH, usually in this order (though perhaps with other directories between them, and certainly with more directories around them).
To inspect your current PATH value, try
echo "$PATH"
or for a slightly more human-readable rendering
echo "${PATH//:/$'\n'}" # bash only
or
echo "$PATH" | tr ':' '\012' # any POSIX system
If you managed to set your PATH to an invalid value (which would cause simple commands like ls and cat to no longer be found, and produce command not found errors) you can try
PATH=/usr/local/bin:/usr/bin:/usr
to hopefully at least restore the essential functionality so that you can use cp or a simple system editor to get back to the original, safe, system default PATH.

How to install python 3 via mac terminal?

I did
brew install python3
when i run python --version it shows 2.7
Document says:
If you still see 2.7 ensure in PATH /usr/local/bin/ takes precedence over /usr/bin/
How do I go about this?
First, you'll want to verify the problem is as stated.
Try running e.g.
> echo $PATH
/usr/local/bin:/Users/jsh/code/go/bin:/usr/bin:/bin:/usr/local/sbin:/usr/texbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
You'll notice that the output is a series of paths separated by ':' characters. Your terminal looks in those locations, in order, until it finds something that matches your command (in this case 'python') and it runs that binary.
This means that earlier items take precedence over later items. You'll note that in my listing, /usr/local/bin/ is at the very beginning, and /usr/bin/ is somewhat later in the listing.
If your listing also has this ordering, you're getting a misleading message, and will need to dig deeper. Hopefully, however, you will find that either /usr/local/bin/ isn't in your list at all, or it is for some reason occurring after /usr/bin/. That's good -- you've now identified the problem -- and we're now at your nominal question, vis: how do you change the ordering?
The environment variable $PATH can be modified by any number of startup tools. There are probably ways to systematically observe all the things that are editing your $PATH, but what I would do is
1) Search in your home directory for things that might be messing with $PATH, something like:
> egrep -d skip -l PATH .*
.gvimrc
.zhistory
.zshrc
.zhistory, here, is a red herring -- it's a list of the stuff I've done in my shell, so I can ignore it.
.gvimrc is also misleading, because it's actually setting $GOPATH, not $PATH.
So the only configuration file I have messing with my $PATH, at least in my home directory, is .zshrc, the config file for my shell itself. This is typically true, and you can just start by assuming this, but it's always good to do a quick search...
2) Edit the responsible file until it is setting PATH so that /usr/bin/local/ precedes /usr/bin/. Open the file in your choice of editor and either modify the line that sets PATH, or add a line that prepends /usr/local/bin/ to PATH (if you go with the latter, make sure that prepend happens after all other modifications to the variable).
For example, my .zshrc has a block like this:
# PATH setup (Starting with hard reset)
export PATH=/sbin
export PATH=/usr/sbin:$PATH
export PATH=/usr/texbin:$PATH
export PATH=/usr/local/sbin:$PATH
export PATH=/bin:$PATH
export PATH=/usr/bin:$PATH
export PATH=/Users/jsh/code/go/bin:$PATH
export PATH=/usr/local/bin:$PATH
(Note that the FINAL LINE is the one prepending /usr/local/bin !)
Then restart your shell (or prompt it to reload the config file, but I'm betting if you knew how to do that, you wouldn't have needed this guidance!). Now re-run 'echo $PATH', and verify that the ordering is correct. If so, try running python again, and you should have an uncle named Bob.
Good luck!

Create executable file for comand line Linux

When ever I log into Linux I usually go straight to the same folder i was wondering if in stead of typing in:
$cd Document/..../..../..../..../....
I could create an executable so I could just type ./csFolder and it would go straight there.
You can add a shell function in your .bashrc and restart your terminal:
csf() {
cd Document/..../..../..../..../....
}
Whenever you want to go to that directory, you just run csf.
Yo can do a symlink
ln -s /path/to/file /path/to/symlink
In addition to the other options (though if you use the function/alias option you want to use an absolute path to the target directory so it works from wherever you happen to be) you can use the environment variable CDPATH to help with this if you have a location you often go to from various other locations.
From the POSIX specification:
CDPATH
A -separated list of pathnames that refer to directories. The cd utility shall use this list in its attempt to change the directory, as described in the DESCRIPTION. An empty string in place of a directory pathname represents the current directory. If CDPATH is not set, it shall be treated as if it were an empty string.
Which means that if you set CDPATH to the parent of your target directory you can just use cd dirname from anywhere and go directly to the directory you wanted to be in.

Add a bash script to path

I want to add a small script to the linux PATH so I don't have to actually run it where it's physically placed on disk.
The script is quite simple is about giving apt-get access through a proxy I made it like this:
#!/bin/bash
array=( $# )
len=${#array[#]}
_args=${array[#]:1:$len}
sudo http_proxy="http://user:password#server:port" apt-get $_args
Then I saved this as apt-proxy.sh, set it to +x (chmod) and everything is working fine when I am in the directory where this file is placed.
My question is : how to add this apt-proxy to PATH so I can actually call it as if it where the real apt-get ? [from anywhere]
Looking for command line only solutions, if you know how to do by GUI its nice, but not what I am looking for.
Try this:
Save the script as apt-proxy (without the .sh extension) in some directory, like ~/bin.
Add ~/bin to your PATH, typing export PATH=$PATH:~/bin
If you need it permanently, add that last line in your ~/.bashrc. If you're using zsh, then add it to ~/.zshrc instead.
Then you can just run apt-proxy with your arguments and it will run anywhere.
Note that if you export the PATH variable in a specific window it won't update in other bash instances.
You want to define that directory to the path variable, not the actual binary e.g.
PATH=$MYDIR:$PATH
where MYDIR is defined as the directory containing your binary e.g.
PATH=/Users/username/bin:$PATH
You should put this in your startup script e.g. .bashrc such that it runs each time a shell process is invoked.
Note that order is important, and the PATH is evaluated such that if a script matching your name is found in an earlier entry in the path variable, then that's the one you'll execute. So you could name your script as apt-get and put it earlier in the path. I wouldn't do that since it's confusing. You may want to investigate shell aliases instead.
I note also that you say it works fine from your current directory. If by that you mean you have the current directory in your path (.) then that's a potential security risk. Someone could put some trojan variant of a common utility (e.g. ls) in a directory, then get you to cd to that directory and run it inadvertently.
As a final step, after following the solution form proposed by #jlhonora (https://stackoverflow.com/a/20054809/6311511), change the permissions of the files in the folder "~/bin". You can use this:
chmod -R 755 ~/bin
make an alias to the executable into the ~/.bash_profile file and then use it from anywhere or you can source the directory containing the executables you need run from anywhere and that will do the trick for you.
adding to #jlhonora
your changes in ~./bashrc or ~./zshrc won't reflect until you do
source ~./zshrc or source ./bashrc , or restart your pc

creating a reference for script

I want to make the following kind of reference:
"ls" command, for example, is universally available in most *nix environments. User can type in from anywhere to execute the scripts.
So, I write script "x". I want to make sure that from wherever the user type in x, the actual script "x" is referenced.
Thus, if I have script "x" stored in home/user/Desktop directory, I should not have to reference the script as follow:
home/user/Desktop/x
I should be able to do:
x
Thanks!
You want to add the directory to your PATH. E.g.
PATH="$PATH:/home/user/someDirectory"
You can add this line to .bash_profile to do it on startup. However, you probably shouldn't add Desktop to the path because some browsers download to there by default (though it shouldn't be executable by default).
You can also put your script in an existing directory that's already in your path such as /usr/local/bin or create a symlink there to your script's location.
cp /home/user/Desktop/x /usr/local/bin
or
mv /home/user/Desktop/x /usr/local/bin
or
ln -s /home/user/Desktop/x /usr/local/bin
Don't mean to be obnoxiously repetitive, but this is my first time answering a question, I can't reply to someone's already-good answer, and I think they are missing some important bits.
First, if you want to make sure everyone can access the script, you'll need to be sure everyone has execute permissions:
chmod a+x /path/to/script.sh
You'll also want to make sure it's in somewhere $PATH references (as the other answers mentioned):
echo $PATH # place the script in one of these directories
I would personally prefer /usr/local/bin, since that's considered the place for custom global scripts. Something the other answers didn't mention is that, if you do want to use a directory besides one in $PATH (say, /opt/myscriptfolder/) you'll want to add another PATH entry at the end of /etc/profile:
PATH="$PATH:/opt/myscriptfolder/"
By putting this in the end of /etc/profile, all users will receive this modified PATH variable on their next login.

Resources