将重复项保留在源上的 $PATH 之外

将重复项保留在源上的 $PATH 之外

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
}

我可以像这样使用它们来附加或前置到$PATHor $MANPATH (它们将与任何格式类似的变量一起使用$PATH):

prepend_path PATH $macPortsDir/sbin
prepend_path MANPATH $macPortsDir/man

答案4

您可以做的一件事是使用环境变量作为保护。因此将环境设置为__<your script>__path_added.

在您的脚本中,您可以在添加路径之前测试是否已设置。有点像 C 标头防护。

相关内容