source
我有以下由我的 -d代码.shellrc
PATH="${PATH}:${HOME}/perl5/bin"
PATH="${PATH}:${HOME}/.bin"
export PATH
但是,如果我对其他代码进行更改,然后对source
这个文件进行更改,则每个源的路径会变得越来越长,每次都会在它们已经存在时附加这些源。我可以做什么来防止这种情况发生?
答案1
add_to_PATH () {
for d; do
d=$({ cd -- "$d" && { pwd -P || pwd; } } 2>/dev/null) # canonicalize symbolic links
if [ -z "$d" ]; then continue; fi # skip nonexistent directory
case ":$PATH:" in
*":$d:"*) :;;
*) PATH=$PATH:$d;;
esac
done
}
add_to_PATH ~/perl5/bin ~/.bin
符号链接规范化行是可选的。如果删除它,还要删除下一行(如果您想保留不存在的目录),或将其更改为
if ! [ -d "$d" ]; then continue; fi
请注意,符号链接规范化方法仅保证此函数添加的目录之间的唯一性。它也不处理边缘情况,例如安装在两个位置的 NFS 目录或 Linux 绑定安装。
答案2
您可以围绕“将此目录附加到路径”命令进行测试,该命令将在添加之前检查是否foo
已在路径中,但这不会给您带来太多好处。
首先,与附加重复元素相比,测试本身的成本会很高。其次,路径中后面的冗余元素对执行给定命令时执行的内容没有影响,因为路径中第一个匹配的可执行文件仍然是执行的。最后,大多数 shell 会在哈希表中缓存先前的路径命中,因此第二次执行时my_command
甚至不会搜索该路径。
不附加冗余条目唯一能让您看到的是一条看起来更漂亮的路径,但大多数路径一开始都非常丑陋。如果这个审美目标对您来说真的很重要,请告诉我们您正在使用哪个 shell,我可以想出一个函数来“仅当它不存在时才将其附加到路径”函数。
答案3
我使用的这些函数源自 os x 上 fink 的初始化脚本(因此功劳归于 fink 开发人员)。它们工作得很好,我可以随时重新获取我的 .bash_profile 资源。不要问我它们是如何工作的...我只知道它们是这样的:)
# define append_path and prepend_path to add directory paths, e.g. PATH, MANPATH
# add to end of path
append_path()
{
if ! eval test -z "\"\${$1##*:$2:*}\"" -o -z "\"\${$1%%*:$2}\"" -o -z "\"\${$1##$2:*}\"" -o -z "\"\${$1##$2}\"" ; then
eval "$1=\$$1:$2"
fi
}
# add to front of path
prepend_path()
{
if ! eval test -z "\"\${$1##*:$2:*}\"" -o -z "\"\${$1%%*:$2}\"" -o -z "\"\${$1##$2:*}\"" -o -z "\"\${$1##$2}\"" ; then
eval "$1=$2:\$$1"
fi
}
我可以像这样使用它们来附加或前置到$PATH
or $MANPATH
(它们将与任何格式类似的变量一起使用$PATH
):
prepend_path PATH $macPortsDir/sbin
prepend_path MANPATH $macPortsDir/man
答案4
您可以做的一件事是使用环境变量作为保护。因此将环境设置为__<your script>__path_added
.
在您的脚本中,您可以在添加路径之前测试是否已设置。有点像 C 标头防护。