在我的某些终端窗口中,PATH
变量中有重复的条目;如下所示:
PATH=/a/b:/c/d:/a/b:/c/d:/e/f:/a/b
我猜罪魁祸首是我的一些脚本中的如下几行:
PATH=/a/b:$PATH
找到这个、那个之后,这个又PATH
变得很长。这是问题:
是否有bash
命令来清除PATH
和类似的环境变量?它应该是一个bash
脚本,因为不能执行实用程序并期望它更改调用 shell 的环境。
在上面的例子中,清理后PATH
看起来应该是这样的:
PATH=/a/b:/c/d:/e/f
答案1
最好不要创建重复项,而不是事后尝试删除它们。使用我在.bashrc
添加私人bin/
目录时使用的技术可以轻松避免这种情况:
[ "${PATH#*$HOME/bin:}" == "$PATH" ] && export PATH="$HOME/bin:$PATH"
我在进行更新时执行了此操作.bashrc
,并且想在不重新启动 shell 的情况下重新运行它。
如果要在末尾添加目录,$PATH
则需要使用前导冒号:
[ "${PATH#*:$HOME/bin}" == "$PATH" ] && export PATH="$PATH:$HOME/bin"
您可以使用参数扩展来逐步PATH
删除重复项,但这有点复杂,而且您需要决定应该保留哪个位置。大致如下:-
OLDPATH="$PATH"; NEWPATH=""; colon=""
while [ "${OLDPATH#*:}" != "$OLDPATH" ]
do entry="${OLDPATH%%:*}"; search=":${OLDPATH#*:}:"
[ "${search#*:$entry:}" == "$search" ] && NEWPATH="$NEWPATH$colon$entry" && colon=:
OLDPATH="${OLDPATH#*:}"
done
NEWPATH="$NEWPATH:$OLDPATH"
export PATH="$NEWPATH"
在匆忙写下这篇文章并测试它之后,我应该已经消除了大部分错误,它应该是一个足够的指南,指导你需要做什么。它留下了最后的任何重复的发生,如果您首先使用我的脚本来避免重复,它们就会出现在这里。在脚本中,当然需要使用.
/source
命令来调用它。
答案2
我编写了这个简单的 Python 3 脚本:
import os
# grab $PATH
path = os.environ['PATH'].split(':')
# normalize all paths
path = map(os.path.normpath, path)
# remove duplicates via a dictionary
clean = dict.fromkeys(path)
# combine back into one path
clean_path = ':'.join(clean.keys())
# dump to stdout
print(f"PATH={clean_path}")
我将脚本放在中$HOME/scripts
,然后将此行添加到我的末尾.bashrc
:
eval $(python3 $HOME/scripts/clean-path.py)
从 Python 3.7 开始,字典保证保留顺序,因此clean_path
目录的顺序与原始目录的顺序相同PATH
。
答案3
以下是 bash 示例。
#!/bin/bash
if [ -n "$PATH" ]; then
old_PATH=$PATH:; PATH=
while [ -n "$old_PATH" ]; do
x=${old_PATH%%:*} # the first remaining entry
case $PATH: in
*:"$x":*) ;; # already there
*) PATH=$PATH:$x;; # not there yet
esac
old_PATH=${old_PATH#*:}
done
PATH=${PATH#:}
unset old_PATH x
fi
echo ${PATH}
答案4
这是一个漂亮的印刷版本
if [[ -x /usr/bin/awk ]]; then
export PATH="$(echo "$PATH" | /usr/bin/awk 'BEGIN { RS=":"; } { sub(sprintf("%c$", 10), ""); if (A[$0]) {} else { A[$0]=1; printf(((NR==1) ?"" : ":") $0) }}')"
echo $PATH
else
echo "AWK is not located at /usr/bin/awk" # for the truly paranoid
fi
下面是单行版本
if [[ -x /usr/bin/awk ]]; then export PATH="$(echo "$PATH" | /usr/bin/awk 'BEGIN { RS=":"; } { sub(sprintf("%c$", 10), ""); if (A[$0]) {} else { A[$0]=1; printf(((NR==1) ?"" : ":") $0) }}')" ; fi