Skip to content

Latest commit

 

History

History
283 lines (191 loc) · 13.9 KB

File metadata and controls

283 lines (191 loc) · 13.9 KB
title 如何将目录添加到你的 PATH
date 2025-02-13 12:27:56 UTC
authorURL
originalURL https://jvns.ca/blog/2025/02/13/how-to-add-a-directory-to-your-path/
translator
reviewer

• [terminal][1] •

今天我和一个朋友讨论如何将目录添加到你的 PATH。对于我这种长期使用终端的人来说,这感觉很"显而易见",但当我搜索如何做这件事的说明时,我实际上找不到解释所有步骤的内容——很多只是说"将这个添加到~/.bashrc",但如果你不使用 bash 怎么办?如果你的 bash 配置实际上在不同的文件中怎么办?而且你应该如何确定要添加哪个目录呢?

所以我想尝试写下一些更完整的指导,并提及我多年来遇到的一些陷阱。

以下是目录:

如果你不确定你使用的是什么 shell,这里有一种方法可以找出来。运行这个:

ps -p $$ -o pid,comm=
  • 如果你使用的是 bash,它会打印出 97295 bash
  • 如果你使用的是 zsh,它会打印出 97295 zsh
  • 如果你使用的是 fish,它会打印出一个错误,比如 "In fish, please use $fish_pid"($$ 在 fish 中不是有效的语法,但无论如何错误消息告诉你你正在使用 fish,这你可能已经知道了)

另外,bash 是 Linux 的默认 shell,而 zsh 是 Mac OS 的默认 shell(截至 2024 年)。在这些指导中,我只会涵盖 bash、zsh 和 fish。

  • 在 zsh 中,它可能是 ~/.zshrc
  • 在 bash 中,它可能是 ~/.bashrc,但这很复杂,请参阅下一节中的说明
  • 在 fish 中,它可能是 ~/.config/fish/config.fish(如果你想 100% 确定,可以运行 echo $__fish_config_dir

Bash 有三个可能的配置文件:~/.bashrc~/.bash_profile~/.profile

如果你不确定你的系统设置使用哪一个,我建议通过这种方式测试:

  1. 在你的 ~/.bashrc 中添加 echo hi there
  2. 重启你的终端
  3. 如果你看到 "hi there",这意味着 ~/.bashrc 正在被使用!太好了!
  4. 否则,删除它并尝试对 ~/.bash_profile 做同样的事情
  5. 如果前两个选项不起作用,你也可以尝试 ~/.profile

(有很多复杂的流程图解释了 bash 如何决定使用哪个配置文件,但在我看来,没有必要去内化它们,直接测试是确定的最快方法)

假设你正在尝试安装并运行一个名为 http-server 的程序,但它不起作用,像这样:

$ npm install -g http-server
$ http-server
bash: http-server: command not found

你如何找到 http-server 在哪个目录中?老实说,一般来说这并不容易——通常答案是"取决于 npm 的配置方式"。一些想法:

  • 通常在设置新的安装程序(如 cargonpmhomebrew 等)时,当你首次设置它时,它会打印出一些关于如何更新你的 PATH 的指导。所以如果你注意的话,你可以在那时获得指导。
  • 有时安装程序会自动更新你的 shell 配置文件以更新你的 PATH
  • 有时只是谷歌搜索"npm 在哪里安装东西?"就会找到答案
  • 一些工具有一个子命令,告诉你它们配置安装东西的位置,比如:
    • Node/npm:npm config get prefix(然后附加 /bin/
    • Go:go env GOPATH(然后附加 /bin/
    • asdf:asdf info | grep ASDF_DIR(然后附加 /bin//shims/

一旦你找到了一个你认为可能是正确的目录,确保它确实是正确的!例如,我发现在我的机器上,http-server~/.npm-global/bin 中。我可以通过尝试在该目录中运行程序 http-server 来确保它是正确的目录,像这样:

$ ~/.npm-global/bin/http-server
Starting up http-server, serving ./public

它工作了!现在你知道你需要添加到 PATH 的目录是什么,让我们进入下一步!

现在我们有了需要的 2 个关键信息:

  1. 你试图添加到 PATH 的目录(如 ~/.npm-global/bin/
  2. 你的 shell 配置在哪里(如 ~/.bashrc~/.zshrc~/.config/fish/config.fish

现在你需要添加的内容取决于你的 shell:

bash 指导:

打开你的 shell 配置文件,添加一行像这样的内容:

export PATH=$PATH:~/.npm-global/bin/

(显然,用你实际尝试添加的目录替换 ~/.npm-global/bin

zsh 指令:

你可以做与 bash 相同的事情,但 zsh 也有一些稍微更高级的语法,如果你喜欢的话:

path=(
  $path
  ~/.npm-global/bin
)

fish 指令:

在 fish 中,语法不同:

set PATH $PATH ~/.npm-global/bin

(在 fish 中你也可以使用 fish_add_path,关于这个的一些说明在下面

现在,一个非常重要的步骤:如果你不重启 shell,更新 shell 配置不会生效!

有两种方法可以做到这一点:

  1. 打开一个新的终端(或终端标签),也许关闭旧的以避免混淆
  2. 运行 bash 启动一个新的 shell(如果你使用的是 zsh,则运行 zsh,如果你使用的是 fish,则运行 fish

我发现这两种方法通常都可以正常工作。

你应该完成了!尝试运行你想运行的程序,希望它现在能工作。

如果不行,这里有一些你可能遇到的问题:

如果运行了错误版本的程序,你可能需要将目录添加到 PATH 的_开头_而不是结尾。

例如,在我的系统上,我安装了两个版本的 python3,我可以通过运行 which -a 看到:

$ which -a python3
/usr/bin/python3
/opt/homebrew/bin/python3

你的 shell 将使用的是列出的第一个

如果你想使用 Homebrew 版本,你需要将该目录(/opt/homebrew/bin)添加到 PATH 的开头,在你的 shell 配置文件中放入这个(它是 /opt/homebrew/bin/:$PATH 而不是通常的 $PATH:/opt/homebrew/bin/

export PATH=/opt/homebrew/bin/:$PATH

或者在 fish 中:

set PATH ~/.cargo/bin $PATH

所有这些指导只有在你从你的 shell 运行程序时才有效。如果你从 IDE、GUI、cron 作业或其他方式运行程序,你需要以不同的方式将目录添加到你的 PATH,具体细节可能取决于情况。

在 cron 作业中

一些选项:

  • 使用你正在运行的程序的完整路径,如 /home/bork/bin/my-program
  • 将你想要的完整 PATH 作为 crontab 的第一行(类似于 PATH=/bin:/usr/bin:/usr/local/bin:……)。你可以通过运行 echo "PATH=$PATH" 获取你在 shell 中使用的完整 PATH。

我老实说不确定如何在 IDE/GUI 中处理它,因为我很久没有遇到这种情况了,如果有人指点我正确的方向,我会在这里添加指导。

如果你编辑你的 path 并通过运行 bash(或 zsh,或 fish)启动一个新的 shell,你通常会得到重复的 PATH 条目,因为每次你启动 shell 时,shell 都会继续向你的 PATH 添加新东西。

就我个人而言,我认为我没有遇到过这种重复会破坏任何东西的情况,但如果你试图理解 PATH 的内容,重复可能会使调试 PATH 发生的事情变得更加困难。

一些处理方法:

  1. 如果你正在调试你的 PATH,打开一个新的终端来做,这样你就会得到一个"新鲜"的状态。这应该避免重复。
  2. 在你的 shell 配置的末尾去重你的 PATH(例如在 zsh 中,显然你可以用 typeset -U path 做到这一点)
  3. 添加目录时检查它是否已经在你的 PATH 中(例如在 fish 中,我相信你可以用 fish_add_path --path /some/directory 做到这一点)

如何去重你的 PATH 是特定于 shell 的,并且并不总是有内置的方法来做到这一点,所以你需要查找如何在你的 shell 中完成它。

这里有一个在 bash 或 zsh 中容易陷入的情况:

  1. 运行一个命令(它失败了)
  2. 更新你的 PATH
  3. 运行 bash 重新加载你的配置
  4. 按几次向上箭头重新运行失败的命令(或打开一个新的终端)
  5. 失败的命令不在你的历史记录中!为什么?

这是因为在 bash 中,默认情况下,历史记录直到你退出 shell 才会保存。

一些修复选项:

  • 不要运行 bash 重新加载你的配置,而是运行 source ~/.bashrc(或在 zsh 中运行 source ~/.zshrc)。这将在你当前会话中重新加载配置。
  • 配置你的 shell 持续保存你的历史记录,而不是只在 shell 退出时保存历史记录。(如何做到这一点取决于你是使用 bash 还是 zsh,zsh 中的历史选项有点复杂,我不太确定最好的方法是什么)

当你第一次安装 cargo(Rust 的安装程序)时,它给你这些关于如何设置 PATH 的指导,这些指导根本没有提到特定的目录。

This is usually done by running one of the following (note the leading DOT):

. "$HOME/.cargo/env"        	# For sh/bash/zsh/ash/dash/pdksh
source "$HOME/.cargo/env.fish"  # For fish

这个想法是你将该行添加到你的 shell 配置中,他们的脚本会自动为你设置 PATH(可能还有其他东西)。

这是相当常见的(例如 Homebrew 建议你执行 brew shellenv),有两种方法可以处理这个:

  1. 只做工具建议的事情(比如将 . "$HOME/.cargo/env" 添加到你的 shell 配置中)
  2. 找出他们告诉你运行的脚本会将哪些目录添加到你的 PATH 中,然后手动添加这些目录。以下是我的做法:
    • 在我的 shell 中运行 . "$HOME/.cargo/env"(如果使用 fish,则运行 fish 版本)
    • 运行 echo "$PATH" | tr ':' '\n' | grep cargo 来确定它添加了哪些目录
    • 看到它说 /Users/bork/.cargo/bin 并将其缩短为 ~/.cargo/bin
    • 将目录 ~/.cargo/bin 添加到 PATH(使用本文中的指导)

我认为按照工具建议做没有什么问题(它可能是"最好的方法"!),但个人而言,我通常使用第二种方法,因为我更喜欢确切地知道我正在更改什么配置。

fish 有一个方便的函数叫做 fish_add_path,你可以运行它来将目录添加到你的 PATH,像这样:

fish_add_path /some/directory

这很酷(这是一个如此简单的命令!)但我已经停止使用它,原因有几个:

  1. 有时 fish_add_path 会更新未来每个会话的 PATH(使用"通用变量"),有时它只会更新当前会话的 PATH,我很难分辨它会做哪一个。理论上文档解释了这一点,但我无法理解它们。
  2. 如果你几周或几个月后需要从你的 PATH 中_移除_目录,因为也许你犯了一个错误,这有点难做到(不过在这个 github issue 的评论中有指导)。

希望这能帮助一些人。如果你在将目录添加到 PATH 时遇到了其他主要陷阱,或者你对这篇文章有疑问,请让我知道(在 Mastodon 或 Bluesky 上)!