Pergunta

I want to add ./bin directory (which is relative to current shell directory) to $PATH on fish startup. Note that fish is a shell.

echo $PATH
set PATH ./bin $PATH
echo $PATH

If I place these lines inside ~/.config/fish/config.fish the shell will echo the same collection of paths. Absolute paths are added properly.

If I open the shell and type the same set PATH ./bin $PATH inside some directory containing bin it is added successfully. However when there is no bin inside current directory it shows me an error.

set: Could not add component ./bin to PATH.
set: Value too large to be stored in data type

I'm running fish 1.23.1 on OS X Lion.

Foi útil?

Solução 5

It seems like fish won't add a non-existing directory path to PATH. That applies to relative paths too. But if you create bin directory in your home directory set PATH ./bin $PATH will work properly on each startup since it is executed from home. This is kind of a hack though.

Outras dicas

The best way I have found to persistently add a path to your $PATH is

set -U fish_user_paths $fish_user_paths ~/path/name

This prepends to $PATH. And since it's persistent, the path stays in $PATH on shell restarts.

It's more efficient than putting a command in your config.fish to modify your $PATH, because it only runs once compared to running on every shell restart.

The variable fish_user_paths is intended to be set by the user1, as stated by ridiculousfish, the maintainer of fish.


Consider creating a fish function for convenience: 2

# ~/.config/fish/functions/add_to_path.fish
function add_to_path --description 'Persistently prepends paths to your PATH'
  set --universal fish_user_paths $fish_user_paths $argv
end

And use it as:

$ add_to_path foo bar  # Adds foo/ and bar/ to your PATH

Notes

  1. On that page the author gives the example set -U fish_user_paths ~/bin. This overwrites fish_user_paths with a single value of ~/bin. To avoid losing existing paths set in fish_user_paths, be sure to include $fish_user_paths in addition to any new paths being added (as seen in my answer).

  2. My dotfiles contain a slightly more advanced version that skips adding duplicates https://github.com/dideler/dotfiles/blob/master/.config/fish/functions/add_to_user_path.fish

I'd never heard of fish before this. I just installed it so I could try it out (and deleted a few paragraphs I had written here before realizing that fish is a shell).

It looks like set PATH dir-name $PATH is the right syntax to prepend a directory to $PATH.

But adding a relative directory name to $PATH is almost certainly a bad idea, and your shell is doing you a favor by warning you when the directory doesn't exist. (fish is designed to be user-friendly.)

Use an absolute path instead:

set PATH $PWD/bin $PATH

and first check whether $PWD/bin exists, printing an error message if it doesn't.

As for the "set: Value too large to be stored in data type" message, could you be adding the directory to your $PATH multiple times? There should be some way to check whether a directory is already in $PATH before adding it.

I think the answer is that using set -U is a red herring. Instead, add the following to ~/.config/fish/config.fish:

if status --is-interactive
    set PATH $PATH ~/.local/bin;
end

direnv http://direnv.net/ is a good utility to help with what you're doing.

Generally, prepending $PATH with ./bin is insecure, as anyone with write-access to a shared directory could hide malicious code in e.g. ./bin/ls. That code would execute when you run ls in the shared directory.

direnv does not solve this problem (it works based on .envrc files, but anyone could be placing those), but at the very least it makes you aware when you cd into a directory that $PATH is getting modified:

$ cd my_project
direnv: loading .envrc
direnv export: ~PATH
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top