Pao*_*olo 1174 bash path environment-variables bashrc
我想知道必须向PATH
环境变量添加新路径的位置。我知道这可以通过编辑来完成.bashrc
(例如),但不清楚如何做到这一点。
这边走:
export PATH=~/opt/bin:$PATH
Run Code Online (Sandbox Code Playgroud)
或这个?
export PATH=$PATH:~/opt/bin
Run Code Online (Sandbox Code Playgroud)
Gil*_*il' 1316
PATH=$PATH:~/opt/bin
Run Code Online (Sandbox Code Playgroud)
或者
PATH=~/opt/bin:$PATH
Run Code Online (Sandbox Code Playgroud)
取决于您是想~/opt/bin
在末尾添加(在所有其他目录之后搜索,以防在多个目录中存在同名程序)还是在开头添加(在所有其他目录之前搜索)。
您可以同时添加多个条目。PATH=$PATH:~/opt/bin:~/opt/node/bin
或订购工作的变化就好了。不要放在export
行首,因为它有额外的复杂性(参见下面的“关于除 bash 之外的 shell 的注意事项”)。
如果您PATH
由许多不同的组件构建,则最终可能会出现重复的条目。请参阅如何添加由 Unix 哪个命令发现的主目录路径?并使用 awk 命令删除重复的 $PATH 条目以避免添加重复项或删除它们。
~/bin
顺便说一下,有些发行版会自动放入您的 PATH(如果存在)。
放线修改PATH
的~/.profile
,或者~/.bash_profile
如果这就是你所拥有的。
注意,~/.bash_rc
不是任何程序读取的,~/.bashrc
是bash交互实例的配置文件。您不应在~/.bashrc
. 定义环境变量的正确位置,例如PATH
is ~/.profile
(或者~/.bash_profile
如果您不关心 bash 以外的 shell)。请参阅它们之间有什么区别,我应该使用哪一种?
不要把它放进去/etc/environment
或~/.pam_environment
:这些不是 shell 文件,你不能像$PATH
那里那样使用替换。在这些文件中,您只能覆盖一个变量,而不能添加到它。
export
如果变量已经在环境中,则不需要:变量值的任何变化都会反映在环境PATH
中。¹ 几乎总是在环境中;所有的 Unix 系统很早就设置了它(实际上通常在第一个进程中)。
在登录时,您可以依赖PATH
已经在环境中,并且已经包含一些系统目录。如果您正在编写可能在设置某种虚拟环境时提前执行的脚本,您可能需要确保它PATH
是非空的并已导出:如果PATH
仍未设置,则类似PATH=$PATH:/some/directory
将设置PATH
为:/some/directory
,以及空组件开头表示当前目录(如.:/some/directory
)。
if [ -z "${PATH-}" ]; then export PATH=/usr/local/bin:/usr/bin:/bin; fi
Run Code Online (Sandbox Code Playgroud)
在bash和ksh和zsh的,export
是特殊的语法,都PATH=~/opt/bin:$PATH
和export PATH=~/opt/bin:$PATH
连做正确的事。在其他 Bourne/POSIX 样式的 shell 中,例如 dash(/bin/sh
在许多系统上),export
被解析为普通命令,这意味着两个不同之处:
~
仅在单词的开头解析,除了在赋值中(请参阅如何添加由 Unix 哪个命令发现的主目录路径?有关详细信息);$PATH
外面的双引号符如果PATH
包含空格或\[*?
。所以在像破折号这样的 shell 中,设置export PATH=~/opt/bin:$PATH
PATH
为文字字符串,~/opt/bin/:
后跟PATH
第一个空格的值。
PATH=~/opt/bin:$PATH
(一个简单的任务)不需要引号并且做正确的事情。如果要export
在可移植脚本中使用,则需要编写export PATH="$HOME/opt/bin:$PATH"
, or PATH=~/opt/bin:$PATH; export PATH
(或PATH=$HOME/opt/bin:$PATH; export PATH
为了可移植到甚至不接受export var=value
也不进行波浪号扩展的 Bourne shell )。
¹这在 Bourne shell 中并非如此(如在实际的 Bourne shell 中,而不是现代 POSIX 样式的 shell),但是现在您极不可能遇到这样的旧 shell。
Ulr*_*arz 94
无论哪种方式都有效,但它们不做同样的事情:PATH
从左到右检查的元素。在您的第一个示例中,可执行文件 in~/opt/bin
将优先于已安装的可执行文件,例如 in /usr/bin
,这可能是您想要的,也可能不是。
特别是,从安全的观点来看,这是很危险的路径添加到前面,因为如果有人能得到您的写入权限~/opt/bin
,他们可以把,例如,不同ls
在那里,你会那么很可能改用的/bin/ls
没有注意到。现在想象相同的ssh
或您的浏览器或选择......(将 . 放在您的路径中也是如此。)
san*_*lio 60
尝试不使用
PATH=$PATH:~/opt/bin
Run Code Online (Sandbox Code Playgroud)
或者
PATH=~/opt/bin:$PATH
Run Code Online (Sandbox Code Playgroud)
为什么? 选择附加还是前置需要考虑很多因素。其中许多在其他答案中都有涉及,因此我不会在此重复。
重要的一点是,即使系统脚本不使用这个(我不知道为什么)*1,~/opt/bin
向 PATH 环境变量添加路径(例如,)的防弹方法是
PATH="${PATH:+${PATH}:}~/opt/bin"
Run Code Online (Sandbox Code Playgroud)
用于附加(而不是PATH="$PATH:~/opt/bin"
)和
PATH="~/opt/bin${PATH:+:${PATH}}"
Run Code Online (Sandbox Code Playgroud)
用于前置(而不是PATH="~/opt/bin:$PATH"
)
这避免了$PATH
最初为空时的虚假前导/尾随冒号,这可能会产生不良副作用,并可能成为噩梦,难以找到(此答案简要介绍了这种情况awk
)。
说明(来自Shell Parameter Expansion):
Run Code Online (Sandbox Code Playgroud)${parameter:+word}
如果
parameter
为 null 或未设置,则不替换任何内容,否则替换 的扩展word
。
因此,${PATH:+${PATH}:}
扩展为:
PATH
为空或未设置,${PATH}:
,如果PATH
设置。注意:这是针对 bash 的。
$ cat /opt/rh/devtoolset-6/enable
# General environment variables
export PATH=/opt/rh/devtoolset-6/root/usr/bin${PATH:+:${PATH}}
...
Run Code Online (Sandbox Code Playgroud)
小智 40
我对问题 2 感到困惑(因为它是由于一个不相关的问题而从问题中删除的):
在不同行上附加更多路径的可行方法是什么?最初我认为这可以解决问题:
Run Code Online (Sandbox Code Playgroud)export PATH=$PATH:~/opt/bin export PATH=$PATH:~/opt/node/bin
但这不是因为第二个分配不仅 append
~/opt/node/bin
,而且还整个PATH
先前分配。这是一个可能的解决方法:
Run Code Online (Sandbox Code Playgroud)export PATH=$PATH:~/opt/bin:~/opt/node/bin
但为了可读性,我更愿意为一条路径分配一项任务。
如果你说
PATH=~/opt/bin
Run Code Online (Sandbox Code Playgroud)
这就是您的 PATH中的全部内容。PATH 只是一个环境变量,如果你想添加到 PATH,你必须用你想要的内容重建变量。也就是说,您对问题 2 给出的示例正是您想要做的,除非我完全没有抓住问题的要点。
我在我的代码中使用这两种形式。我有一个通用配置文件,我安装在我工作的每台机器上,看起来像这样,以适应可能丢失的目录:
export PATH=/opt/bin:/usr/local/bin:/usr/contrib/bin:/bin:/usr/bin:/usr/sbin:/usr/bin/X11
# add optional items to the path
for bindir in $HOME/local/bin $HOME/bin; do
if [ -d $bindir ]; then
PATH=$PATH:${bindir}
fi
done
Run Code Online (Sandbox Code Playgroud)
Ste*_*own 25
Linux 使用$PATH
环境变量确定可执行搜索路径。要将目录 /data/myscripts 添加到$PATH
环境变量的开头,请使用以下命令:
PATH=/data/myscripts:$PATH
Run Code Online (Sandbox Code Playgroud)
要将该目录添加到路径的末尾,请使用以下命令:
PATH=$PATH:/data/myscripts
Run Code Online (Sandbox Code Playgroud)
但是前面的方法还不够,因为当您在脚本中设置环境变量时,该更改仅在脚本内有效。只有两种方法可以解决此限制:
例子:
$HOME/myscript.sh
source $HOME/myscript.sh
Run Code Online (Sandbox Code Playgroud)
包含基本上将“被调用”脚本合并到“调用”脚本中。它就像 C 中的 #include。所以它在“调用”脚本或程序中是有效的。但是当然,它在调用程序调用的任何程序或脚本中都无效。为了使其在调用链中一直有效,您必须使用导出命令来遵循环境变量的设置。
例如,bash shell 程序通过包含来合并文件 .bash_profile 的内容。将以下 2 行放在 .bash_profile 中:
PATH=$PATH:/data/myscripts
export PATH
Run Code Online (Sandbox Code Playgroud)
有效地将这两行代码放在 bash 程序中。因此,在 bash 中, $PATH 变量包含$HOME/myscript.sh
,并且由于导出语句,bash 调用的任何程序都具有更改的$PATH
变量。并且因为您从 bash 提示符运行的任何程序都由 bash 调用,所以新路径对您从 bash 提示符运行的任何程序都有效。
最重要的是,要将新目录添加到路径中,您必须将目录附加到或预先添加到 shell 中包含的脚本中的 $PATH 环境变量,并且必须导出$PATH
环境变量。
更多信息在这里
小智 22
一段时间以来,我一直使用两个函数pathadd
,pathrm
它们有助于将元素添加到路径中,而无需担心重复。
pathadd
接受一个路径参数和一个可选after
参数,如果提供该参数将附加到PATH
否则它在它前面。
在几乎所有情况下,如果您要添加到路径中,那么您可能希望覆盖路径中已有的任何内容,这就是我选择默认添加的原因。
pathadd() {
newelement=${1%/}
if [ -d "$1" ] && ! echo $PATH | grep -E -q "(^|:)$newelement($|:)" ; then
if [ "$2" = "after" ] ; then
PATH="$PATH:$newelement"
else
PATH="$newelement:$PATH"
fi
fi
}
pathrm() {
PATH="$(echo $PATH | sed -e "s;\(^\|:\)${1%/}\(:\|\$\);\1\2;g" -e 's;^:\|:$;;g' -e 's;::;:;g')"
}
Run Code Online (Sandbox Code Playgroud)
将这些放在您希望更改 PATH 环境的任何脚本中,您现在可以这样做了。
pathadd "/foo/bar"
pathadd "/baz/bat" after
export PATH
Run Code Online (Sandbox Code Playgroud)
如果路径已经存在,您可以保证不会添加到路径中。如果您现在要确保/baz/bat
是在开始。
pathrm "/baz/bat"
pathadd "/baz/bat"
export PATH
Run Code Online (Sandbox Code Playgroud)
现在任何路径都可以移动到前面,如果它已经在路径中而不会加倍。
小智 12
我不能说其他发行版,但 Ubuntu 有一个文件 /etc/environment,这是所有用户的默认搜索路径。由于我的计算机仅供我使用,因此我将我想要的任何目录放在我的路径中,除非它是我放在脚本中的临时添加。
Ami*_*4x7 10
要向PATH
环境变量添加新路径:
export PATH=$PATH:/new-path/
Run Code Online (Sandbox Code Playgroud)
要将此更改应用于您打开的每个 shell,请将其添加到 shell在调用时将作为来源的文件。在不同的 shell 中,这可以是:
例如
# export PATH=$PATH:/root/learning/bin/
# source ~/.bashrc
# echo $PATH
Run Code Online (Sandbox Code Playgroud)
您可以在上面的输出中看到提供的路径。
在某些情况下,它使用PATH=/a/b:$PATH
可能被认为是添加路径的“不正确”方式PATH
:
PATH
相同形式存在的路径。PATH
采用不同形式的路径(即,由于使用符号链接或 导致的别名..
)。PATH
当它打算覆盖PATH
.这个(Bash-only)函数在上述情况下做“正确的事情”(有一个例外,见下文),返回错误代码,并为人类打印好的消息。不需要时可以禁用错误代码和消息。
prepath() {
local usage="\
Usage: prepath [-f] [-n] [-q] DIR
-f Force dir to front of path even if already in path
-n Nonexistent dirs do not return error status
-q Quiet mode"
local tofront=false errcode=1 qecho=echo
while true; do case "$1" in
-f) tofront=true; shift;;
-n) errcode=0; shift;;
-q) qecho=':'; shift;;
*) break;;
esac; done
# Bad params always produce message and error code
[[ -z $1 ]] && { echo 1>&2 "$usage"; return 1; }
[[ -d $1 ]] || { $qecho 1>&2 "$1 is not a directory."; return $errcode; }
dir="$(command cd "$1"; pwd -P)"
if [[ :$PATH: =~ :$dir: ]]; then
$tofront || { $qecho 1>&2 "$dir already in path."; return 0; }
PATH="${PATH#$dir:}" # remove if at start
PATH="${PATH%:$dir}" # remove if at end
PATH="${PATH//:$dir:/:}" # remove if in middle
fi
PATH="$dir:$PATH"
}
Run Code Online (Sandbox Code Playgroud)
例外是此函数不会规范化PATH
通过其他方式添加到的路径,因此如果路径的非规范别名在 中PATH
,这将添加重复项。尝试规范化已经存在的路径PATH
是一个冒险的命题,因为相对路径在传递给prepath
时具有明显的含义,但是当已经在路径中时,您不知道添加时当前工作目录是什么。
小智 6
对我来说(在 Mac OS X 10.9.5 上),将路径名(例如/mypathname
)添加到文件中/etc/paths
效果很好。
编辑前,echo $PATH
返回:
/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin
Run Code Online (Sandbox Code Playgroud)
编辑/etc/paths
并重新启动 shell 后,$PATH 变量将附加/pathname
. 确实,echo $PATH
返回:
/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/mypathname
Run Code Online (Sandbox Code Playgroud)
发生的事情是/mypathname
已附加到$PATH
变量。
这是我的解决方案:
PATH=$(echo -n $PATH | awk -v RS=: -v ORS=: '!x[$0]++' | sed "s/\(.*\).\{1\}/\1/")
Run Code Online (Sandbox Code Playgroud)
一个不错的简单单衬,不会留下拖尾 :
归档时间: |
|
查看次数: |
2783588 次 |
最近记录: |