6

I'm using zsh on ubuntu and I created a symlink for bat as so:

ln -s /usr/bin/batcat /home/user_name/.local/bin/bat

hitting ls -l from ~/.local/bin shows:

lrwxrwxrwx 1 tux tux 15 May 19 13:47 bat -> /usr/bin/batcat

Now from any directory(even in ~/.local/bin),

If I run bat, I get command not found: bat. Also running ~/.local/bin doesn't work. However, running ./bat(from ~/.local/bin) does work. Running batcat also works.

echo $PATH shows that ~/.local/bin is in the path

What could be going wrong here? no symlink works, bat is just an example

P.S. In bash, things are working as expected

Haris Muzaffar
  • 249
  • 2
  • 6
  • 3
    Does `echo $PATH` list `~/.local/bin` with a tilde, or does it list `/home/user_name/.local/bin`? It needs to have the full path. Bash works with `~`, but that isn't really helpful because programs started by bash don't recognize the `~`. Zsh doesn't have this misfeature. – Gilles 'SO- stop being evil' May 19 '21 at 11:28
  • It has a tilde. Works perfectly after adding the full path instead of the tilde. Thanks! – Haris Muzaffar May 19 '21 at 11:38
  • Although replacing tilde with full path worked for me but in vim, fzf `BLines` somehow still says `bat` error, file or directory not found – Haris Muzaffar May 19 '21 at 12:02

1 Answers1

12

If your PATH actually contains ~/.local/bin with the literal tilde character: that won't work. The tilde needs to be expanded to your home directory.

For example, any of these lines are correct in zsh, bash or any other sh-like shell:

PATH=~/.local/bin:$PATH
PATH=$PATH:~/.local/bin
PATH=~/.local/bin:"$PATH"
PATH="$PATH":~/.local/bin
export PATH="$HOME/.local/bin:$PATH"
export PATH="$PATH:$HOME/.local/bin"

They work because ~ is expanded to the home directory when it's at the beginning of a word, immediately after the equal sign in an assignment, or immediately after a : in the right-hand side of an assignment (the purpose of this last rule is precisely for the convenience of setting PATH).

But a line like PATH="~/.local/bin:$PATH" won't work, because ~ is not expanded in double quotes, so the value of PATH ends up containing the literal character ~. This PATH references a directory called ~ in the current directory, not your home directory.

Bash¹ has a feature in which ~ is interpreted as the home directory at the start of path entries. So PATH="~/.local/bin:$PATH" does partially work in bash. However, it only works when you run a program from bash directly, not when programs other than bash themselves start programs. So even if you use bash, don't put a literal ~ in the path, make sure it's expanded or use $HOME instead.


When not in POSIX mode like when running as sh, as that feature breaks POSIX compliance as a PATH='~' is meant to look for commands in the literal ~ subdirectory of the current working directory.

Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175