12

I want to install aria2c manually by copying it to /usr/local/bin since I installed aria2c with apt on /usr/bin

which one of those is going to be executed if I type aria2c?

mohsentux
  • 217
  • 2
  • 5
  • 4
    note that copying executables into places is usually a bad idea – they typically want a specific version of the libraries they're using (namely, one that is ABI-compatible with what they were built with). In fact, I'd wager that "I want to install ... by copying it to /usr/local/bin" comes with more "nope, won't work" than you think. What's the reason you're doing this, instead of, say, using the installation tool from the source code build? – Marcus Müller Dec 27 '21 at 14:52
  • Concur that this is a really bad idea, and if you have to ask this question then you really shouldn't be doing it in the first place. – Shadur-don't-feed-the-AI Dec 28 '21 at 09:13

3 Answers3

23

The executable that will be executed depends on the ordering of the directories in the PATH variable.

If /usr/bin is listed before /usr/local/bin, then /usr/bin/aria2c would be executed rather than /usr/local/bin/aria2c.

If your shell does hashing of executables, and if it has already accessed aria2c from /usr/bin before you installed the same utility in /usr/local/bin, then it may choose /usr/bin/aria2c regardless of the ordering of the directories in PATH. Note that this probably only happens in the specific case where you have used the utility, then install it in another location, and then try to use it again in the same shell session. The command hash -r would clear the remembered locations of utilities in a shell session. See also How do I clear Bash's cache of paths to executables?

If you have an alias or shell function called aria2c, then that would be used before the shell uses PATH to locate the executable.


On my personal (non-Linux) system:

$ printf '%s\n' "$PATH" | tr ':' '\n'
/usr/bin
/bin
/usr/sbin
/sbin
/usr/X11R6/bin
/usr/local/bin
/usr/local/sbin
/usr/games

As you can see, /usr/local/bin is way after /usr/bin on my system. I've set it up like that to avoid accidentally overriding base system utilities in /usr/bin. You likely want the opposite order if you want to give local executables priority over the ones in /usr/bin.

Kusalananda
  • 333,661
4

It's weird I cannot find an answer on this SE website.

It depends on your shell but generally there's the PATH environment variable which contains directories the shell is checking in order to execute a command. Those directories are separated with a semicolon :.

$ echo $PATH
/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/wine/bin:/home/birdie/bin

Binaries are being searched for from left to right, i.e. in my example if I have the same binary in /usr/local/bin and /bin the binary from /usr/local/bin will take precedence.

In the meantime if your shell has aliases, functions support those will be executed first in case they are defined. You can see them by running alias and set. And there's yet another category built-in commands. So the order is:

  • aliases
  • functions
  • built-in commands
  • binaries found in $PATH which is looked up from left to right

Lastly, worth noting and remembering: aliases do not work (not defined) in shell scripts.

  • Not exactly what the question here asked but the answer to this post also answers this OP's question. – doneal24 Dec 27 '21 at 15:28
  • Aliases aren't defined (don't work) because your $HOME/.bashrc checks $- and exits early if it doesn't contain i (interactive). Read man bash, the INVOCATION section. – waltinator Dec 27 '21 at 19:08
  • 3
    @waltinator I'm not sue whose shell init files you're talking about or why you mention bash specifically, but you will notice that aliases are not substituted in non-interactive shells even if they are defined. It has very little to do with your .bashrc checking $-. – Kusalananda Dec 28 '21 at 07:07
0

More simple solution is to use which to see the program that would be executed.

Manpage ...

it prints to stdout the full path of the executables that would have been executed when this argument had been entered at the shell prompt.

example:

[~] echo "$PATH"
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin:/usr/lib/llvm/13/bin:/usr/lib/llvm/12/bin
[~] echo '#!/bin/bash' > hello_world.sh
[~] echo 'echo "Hello World"' >> hello_world.sh
[~] chmod 755 hello_world.sh 
[~] sudo cp hello_world.sh /bin/
[~] sudo cp hello_world.sh /usr/bin/
[~] sudo cp hello_world.sh /usr/local/bin/
[~] which hello_world.sh
/usr/local/bin/hello_world.sh

Addition

It brought to my attention that hash can alter the way commands are executed from. But in most cases the programs aren't hashed cause of a little performance boost. My hash list has only two commands in it, all the time.

[~] hash
hits    command
   3    /usr/bin/man
   1    /bin/bash

As long you don't hash your commands the which command should be fine. Or you use type -p hello_world.sh instead. The type command is part of the bash like hash is. And I assume they will communicate with each other in some way.

To be save you can call the hash command without any arguments to see all the hashed programs.

Mario
  • 196
  • 2
    The which command cannot tell you which command will be executed, because it does not know about the shell's hash table. – Chris Down Dec 28 '21 at 00:50
  • that's new to me and there is nothing in the manpage about some hash tables. This command is designed to do one thing and that doesn't work ?.. can you give me an example – Mario Dec 28 '21 at 01:02
  • Read bash -c 'help hash', and compare with type which, you can trivially reproduce this by hashing a $PATH lookup and then removing the file it points to. which is an external binary and thus cannot know what the shell has already hashed and may choose use, which may not simply be whatever is first in $PATH. Instead of which, either use type -p, or command -v. which is a broken hand-me-down from csh and should not be used. – Chris Down Dec 28 '21 at 01:06
  • thx for the advice. I added/considered this in my post. – Mario Dec 28 '21 at 01:25