更改 zsh 中的 PATH 变量

更改 zsh 中的 PATH 变量

我想更改 zsh 中的 PATH 变量。

问题:我不明白.zshrc文件中的哪些位置必须进行修改。

通常,我会查找 PATH 变量的分配,并从头开始设置我想要的值(保持所有系统二进制文件目录不变)。

我的 .zshrc 文件中的第一行如下:

# If you come from bash you might have to change your $PATH.
# export PATH=$HOME/bin:/usr/local/bin:$PATH

# Path to your oh-my-zsh installation.
export ZSH="/Users/Sam/oh-my-zsh"

export PATH=$PATH:/Applications/Postgres.app/Contents/Versions/13/bin

ETC。

我的实际 PATH 变量是:

/Library/Frameworks/Python.framework/Versions/3.9/bin:/Library/Frameworks/Python.framework/Versions/3.8/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/Postgres.app/Contents/Versions/13/bin

我想删除python3.8所在的目录,它是多余的。

我的问题:

  1. 我是否必须更改 .zshrc 文件中的第 2 行或第 7 行?
  2. 第 2 行被注释掉了...它是否在终端开始时执行?
  3. 我试图注释掉第 7 行。但是 postgres 目录仍然保留在我的 PATH 变量中,我不明白。

答案1

从评论重新发布到答案,但有一些额外的注释。

首先,在网络上搜索有关使用 Un*x shell(命令行)和终端会话的介绍性指南。其中大多数都提供了有关最常见环境变量的大量信息,例如 PATH。 (有些人可能没有提供很多细节不少地方但是,PATH 变量已设置/修改/等。)

其次,了解环境变量是每个实例,这意味着,每个进程在启动时都会获取自己的变量副本(来自父进程),并且有不存在“全球环境”这样的东西。如果您打开两个终端实例,并在其中一个终端中键入export PATH="",清除 PATH 变量,然后在另一个终端中键入 ,则可以看到这一点echo $PATH。您将看到第二个中的 PATH 变量没有受到影响通过第一个终端窗口中的清理。

第三,尽量避免在一个问题中提出多个问题,除非问题都是非常密切相关。

我将在所提出的问题之间来回跳跃(因为它们非常密切相关)。另外,我经常使用bash语法/命令。不同的 shell 可能使用其他形式(例如setvar在 中tcsh)。

你的默认 .zshrc创建用户主目录 ($HOME) 时(通常在创建用户记录时)从骨架(模板)文件复制 - 请记住,如果您的系统管理员修改了 skel 文件,新版本会不是复制到您已经存在的主目录中!)。这些骨架文件通常位于/etc/skel、 等地方可能为特定 shell 定义,或由系统管理员定义。

这些默认/框架文件通常包含常见用法的示例,有时会被注释掉(以“#”为前缀),因此当您在用户主目录中编辑它们时,您可以根据自己的喜好或需要取消注释或编辑它们。

请记住,并非所有这些文件都会自动加载。它们仅在您“登录”时才会加载——有些可能仅在您通过 GUI 登录时才会加载,而其他一些则仅在您登录到文本模式控制台时才会加载。通常,不同的 shell 使用诸如.<shell>rc.bashrc或 之类的名称.zshrc(通常简称为“rc 文件”)来定义登录/启动该 shell 时的默认配置。特别注意这意味着任何如果您从 cron 作业或 GUI 启动器等不加载 shell 及其 rc 文件的程序执行进程,则 rc 文件中设置的命令或变量不可用。

另请记住,外壳确实不是自动地重新加载每次编辑 rc 文件时。要在编辑它们后“重新加载”它们,您需要source .zshrc(或source .bashrc等)或关闭/退出 shell/终端并重新登录。某些 shell 可以强制会话重新加载,您必须阅读 shell 的手册页以了解更多信息怎么做。

当您使用该source .zshrc方法时,您还需要记住以前的设置和值会被保留。这意味着,除非您的 rc 文件显式清除 PATH 变量,否则它将继续包含以前的值并且添加rc 文件添加的任何内容 - 即使先前加载的 rc 文件已经添加了它。例如,将以下代码放入名为“growvar.sh”的文件中:

export GROWVAR="$GROWVAR:Grow!"
echo "GROWVAR now contains \"$GROWVAR\""

并保存它。然后记下以下命令和结果:

$ source growvar.sh
GROWVAR now contains ":Grow!"
$ source growvar.sh
GROWVAR now contains ":Grow!:Grow!"
$ source growvar.sh
GROWVAR now contains ":Grow!:Grow!:Grow!"

(另请注意,您需要这样做source:将文件设置为可执行文件 ( chmod +x ...) 不会按照您的预期进行,因为它将在子 shell 中“执行”而不影响父 shell 进程环境。)

这对于 PATH 通常是无害的,因为大多数 shell 都会跳过检查它已经检查过的 $PATH 的每个部分。他们还忽略“空”路径,例如“::”(实际上是以“:”分隔的空路径)。这就是为什么即使之前未设置 $PATH,`export PATH="$PATH:/new/path/here" 仍然有效。但是,如果向 PATH 变量添加大量长路径,则它可能会因多个冗余路径而变得非常大。 (甚至可能耗尽可用环境空间内存。)

我确信我忘记了一些事情......但这就是它们的联系方式:

问题#1:更改第#7 行——或者..只需将其注释掉并添加“更正”的版本。这样,以后你就可以立即看到你改变了它,改变之前是什么,改变之后又是什么。对骨架文件中注释掉的“示例”代码执行相同的操作。不要取消注释它们:复制代码,根据您的喜好进行调整,然后取消注释副本。

问题#2:如上所述,“#”使该行成为注释行,shell 会简单地忽略它。

问题#3:最有可能的是,您期望更改 rc 文件会自动重新加载它(我上面解释过它不会这样做),或者如果您确实重新加载(通过命令source),您期望 PATH 为清除它的当前值(我上面也解释过并非如此)。您需要完全重新启动/重新加载 shell 才能获取更改。

问题(来自评论)#1:“它从哪里获取 $PATH?”这取决于。最初,PATH 甚至不存在。如果您尝试引用它(如 $PATH 中所示),它只会返回一个空字符串 ("")。一旦您登录到 shell,shell 将自动创建source许多系统默认文件,通常位于/etc/default(以及其他地方,您的 shell 的手册页将为您提供 shell 的详细信息),这些文件设置 PATH 变量以供进一步使用。因此最多示例 PATH 设置使用export PATH="$PATH:/new/path/here",因此它们可以保留任何先前设置的路径(或者如果 PATH 先前不存在则根本不保留)。

问题(来自评论)#2:关于“$HOME/bin”的示例行:许多经验丰富的 Un*x 用户都有自己的 $HOME/bin 目录来提供特定于其登录的自定义命令和覆盖。因此,示例配置行通过将目录添加到 PATH 来演示这一点。 PATH 变量中任何不存在的目录都会被忽略并跳过,不会出现错误。

编辑添加:哦,还有...在未定义 $HOME 的极端情况下,它只是像 PATH 一样被空字符串替换。因此,“$HOME/bin”的计算结果为“/bin”。

另一个“编辑添加”功能可以进一步提供帮助:如果您的目标是简单地清理 PATH,您可以编写一个简单的实用程序来执行此操作 - 但您必须记住,该实用程序只能修改它自己的 PATH 副本。您可以通过让实用程序输出(在标准输出上)清理后的路径来解决此问题,父进程/shell 可以读取该路径来设置新路径。例如:

...
export PATH=`/bin/mypathutil --cleanup`
...

我实际上有一个 TCL 脚本,/bin/cleanpath它输出一个路径,其中每个目录仅给出一次。所以像“/bin:/bin:/usr/bin:/bin:/usr/bin:/usr/games:/bin:/bin”之类的东西会简单地输出“/bin:/usr/bin:usr/games” 。 (从技术上讲,我的脚本做了更多的事情,例如确保我的特殊自定义目录/usr/local/overrides始终位于 PATH 中的第一个,因此我始终可以将自定义命令覆盖在那里。这样,我还可以通过在 /usr/ 中创建符号链接来临时禁用某些命令local/override 只是指向/bin/true. (但是,这可能不适用于 shell 内置程序,或者使用可执行文件的完整路径名的程序...)

相关内容