3

When doing

which python, I am getting /usr/bin/python.

When doing

which python3, I am getting /usr/bin/python3.

However, When doing alias python=/usr/bin/python3, still which python returns /usr/bin/python.

This makes me think there is some more elaborate logic to finding bash commands, but I was not able to look it up, probably I am not aware of its name.

So, how does bash find commands?


EDIT to answer comments

see output of alias

noam@ML:~/src/uv-car-parts-segmentation$ which python
/usr/bin/python
noam@ML:~/src/uv-car-parts-segmentation$ which python3
/usr/bin/python3
noam@ML:~/src/uv-car-parts-segmentation$ alias python=/usr/bin/python3
noam@ML:~/src/uv-car-parts-segmentation$ alias
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
alias ls='ls --color=auto'
alias python='/usr/bin/python3'
noam@ML:~/src/uv-car-parts-segmentation$ which python
/usr/bin/python

Here is the doc about how commands are resolved, which appears not to be the solution to this.

Gulzar
  • 135
  • 6
  • I can't reproduce this. Which OS are you on? What does the command `alias|grep python` show? – Edward Jan 23 '22 at 08:51
  • 2
    Aliases are only applied to the *command* itself. Here, **which** is the command: *python* is merely an argument to a command. you really do not want an alias to be a global replace to everything you type on the command line. – Paul_Pedant Jan 23 '22 at 09:26
  • @Edward it shows nothing, see edit. – Gulzar Jan 23 '22 at 09:46
  • 1
    The reason I couldn't reproduce was that the `which` command itself was aliased on my machine (CentOS 8). Look at this: `alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'`. Running `/usr/bin/which python` _without_ the command flags confirmed the behaviour you saw. The answer by @ilkkachu is correct. – Edward Jan 23 '22 at 10:40

1 Answers1

16

which is usually/often an external command, it doesn't know about shell aliases, or shell functions for that matter. It only looks for the matching command name in PATH.

type python would recognize the alias, and type should work in all POSIXy shells. In at least Bash and some others, type -a can be used to show all matches of the given name. It doesn't track where the alias points to, though, just shows the pathname that would be used if there was no alias:

$ alias python=/usr/bin/python3
$ type -a python
python is aliased to '/usr/bin/python3'
python is /usr/bin/python

See: Why not use "which"? What to use then?

Bash itself would process aliases first, early in the command line processing, then it would check if the first word after all expansions is (1) a function (2) a builtin, or (3) an external command.

(Unless that first word was an unquoted literal keyword like if, in which case it would parsed using the appropriate syntax. You'd need e.g. "if" or /path/to/if to run an external command called if.)

Jeff Schaller
  • 66,199
  • 35
  • 114
  • 250
ilkkachu
  • 133,243
  • 15
  • 236
  • 397
  • 1
    As a side note, `type -a` is not reliably portable, only some shells implement it. `type` _is_ portable provided the shell is POSIX compliant. And, if it’s available and you don’t need the full list of entries like `type -a` gives, you probably want to use `command -V` instead of either because it will properly identify unquoted literal shell keywords without requiring special quoting. – Austin Hemmelgarn Jan 23 '22 at 18:21
  • 1
    @AustinHemmelgarn, yep, clarified. Not sure I can see a difference between `type if` and `command -V if` in any shell I have, though. – ilkkachu Jan 23 '22 at 18:42
  • Indeed, bash, ZSH, and most of the other big FOSS shells internally alias `type` to `command -V` because that’s still POSIX compliant, but you arguably should not rely on that given that POSIX doesn’t require `type` to behave that way for shell keywords. – Austin Hemmelgarn Jan 24 '22 at 13:00