50

When I do

which pip3

I get

/usr/local/bin/pip3

but when I try to execute pip3 I get an error as follows:

bash: /usr/bin/pip3: No such file or directory

This is because I recently deleted that file. Now which command points to another version of pip3 that is located in /usr/local/bin but the shell still remembers the wrong path. How do I make it forget about that path?

The which manual says

which returns the pathnames of the files (or links) which would be executed in the current environment, had its arguments been given as commands in
       a strictly POSIX-conformant shell.  It does this by searching the PATH for executable files matching the names of the arguments. It does not follow
       symbolic links.

Both /usr/local/bin and /usr/bin are in my PATH variable, and /usr/local/bin/pip3 is not a symbolic link, it's an executable. So why doesn't it execute?

spiderface
  • 615
  • 1
  • 6
  • 8
  • What is the content of `/usr/local/bin/pip3`? – Thomas Jan 08 '17 at 16:13
  • Had you previously run `pip3` in that shell while it was in `/usr/bin` and then moved it? – Eric Renouf Jan 08 '17 at 16:14
  • 2
    What do you see if you run `hash -t pip3`? – Eric Renouf Jan 08 '17 at 16:16
  • @Eric Renouf Yes, I had 2 versions of `pip3` and deleted one of them. I edited the question. – spiderface Jan 08 '17 at 16:21
  • if you do a "echo $PATH" you'll see /usr/bin/ and /usr/local/bin. I'd assume that the order is relevant. As a quick fix. just could make a symbolic link and you're good to go: ln -s /usr/local/bin/pip3 /usr/bin/pip3 – Michael D. Jan 08 '17 at 16:23
  • 1
    @Eric Renouf `hash -t pip3` prints `/usr/bin/pip3` – spiderface Jan 08 '17 at 16:24
  • 4
    Unless you have a very good reason, you should always use `type` eather than `which`. `type` is built into a posix shell and tells you what a shell will do, rather than `which` which tries to guess what the shell will do. – icarus Jan 08 '17 at 21:23
  • @spiderface [Why does `type which` say that `which is hashed`?](http://askubuntu.com/q/446580/253474) – phuclv Jan 09 '17 at 08:23

2 Answers2

64

When you run a command in bash it will remember the location of that executable so it doesn't have to search the PATH again each time. So if you run the executable, then change the location, bash will still try to use the old location. You should be able to confirm this with hash -t pip3 which will show the old location.

If you run hash -d pip3 it will tell bash to forget the old location and should find the new one next time you try.

Eric Renouf
  • 18,141
  • 4
  • 49
  • 65
  • 7
    Or `hash -r` to clear the whole table. – mattdm Jan 08 '17 at 16:27
  • Yes, that worked. I think I'll change the title of the question because it has nothing to do with `which`. – spiderface Jan 08 '17 at 16:27
  • Where can I read the usage of the `hash` command? My system only has a very unhelpful manpage that is identical to this one: http://man7.org/linux/man-pages/man3/hash.3.html – spiderface Jan 08 '17 at 21:50
  • 1
    @spiderface for most bash features it's easier to use `help` instead of man, so here `help hash` – Eric Renouf Jan 08 '17 at 21:58
  • 3
    @spiderface `type hash` will tell you that it's a shell builtin, so it doesn't have its own man page. Instead, use `help hash` or look up `hash` in bash's man page. – deltab Jan 08 '17 at 23:14
  • 1
    Or, if you really want to use `man`...since `hash` is a `bash` builtin, you would want `man bash` to find it. But what the man page says is essentially what `help hash` to bash says. – MAP Jan 08 '17 at 23:32
  • This will also reset the PATH cache and IMO is easier to remember: `PATH=$PATH` – jrw32982 Jan 11 '17 at 18:30
  • 3
    Since bash is calling hash -t pip3 underneath, why doesn't it call hash -d pip3 automatically once it discovers the file is not there? Or at least issue a warning and suggestion to run "hash -d pip3"? – Craig Hicks May 19 '18 at 17:36
  • I've tried hash -d and hash -r, AND IT *STILL* USES THE WRONG PATH! (Damn I hate Linux!) – UserX Nov 01 '21 at 20:09
  • @UserX If you run `hash -t ` do you see an entry there? That should show you where `bash` is expecting that name to be found on disk. What is the symptom of "wrong path" for you? – Eric Renouf Nov 01 '21 at 20:32
0

When changing the location of an executable (by moving it or making a new version of an executable available in a different location), use hash -d NAME to force bash to look for it again in PATH. However, if NAME is not in the cache, this will error, so as part of your scripts, use something like this:

if hash -t $NAME >& /dev/null; then 
  hash -d $NAME
fi
Oliver
  • 401
  • 3
  • 8