一种更舒适的编辑长 $PATH 的方法?

Nic*_* M. 35 linux unix bash path

我想在 ~/.bashrc 中添加几个目录到我的 $PATH。

我的 $PATH 很长,所以很难看出它包含哪些目录以及以什么顺序。

我知道我可以修改我的 ~/.bashrc 为:

PATH=$PATH:/some/dir
PATH=$PATH:/another/dir:/yet/another
PATH=$PATH:/and/another
...
Run Code Online (Sandbox Code Playgroud)

它会让它更容易阅读。但我想知道在过去的几年里,Bash 是否已经获得了一些使指定长 PATH 更容易的语法。例如,我在幻想类似于以下的语法:

PATH=:((
  /some/dir
  /another/dir
  /yet/another
  /and/another
  ...
))
Run Code Online (Sandbox Code Playgroud)

知道这样的语法是无效的。我想知道是否有这么简单的事情。在那儿?

Sta*_*ish 25

我使用一组方便的函数来为变量添加或添加路径。这些函数位于名为“pathfuncs”的 contrib 文件中的 Bash 分发 tarball 中。

  • add_path 将条目添加到 PATH 变量的末尾
  • pre_path 将条目添加到 PATH 变量的开头
  • del_path 将从 PATH 变量中删除条目,无论它在哪里

如果您指定一个变量作为第二个参数,它将使用它而不是 PATH。

为方便起见,它们是:

# is $1 missing from $2 (or PATH) ?
no_path() {
    eval "case :\$${2-PATH}: in *:$1:*) return 1;; *) return 0;; esac"
}
# if $1 exists and is not in path, append it
add_path () {
  [ -d ${1:-.} ] && no_path $* && eval ${2:-PATH}="\$${2:-PATH}:$1"
}
# if $1 exists and is not in path, prepend it
pre_path () {
  [ -d ${1:-.} ] && no_path $* && eval ${2:-PATH}="$1:\$${2:-PATH}"
}
# if $1 is in path, remove it
del_path () {
  no_path $* || eval ${2:-PATH}=`eval echo :'$'${2:-PATH}: |
    sed -e "s;:$1:;:;g" -e "s;^:;;" -e "s;:\$;;"`
}
Run Code Online (Sandbox Code Playgroud)

如果将这些添加到 bash 启动文件中,则可以像这样添加到 PATH 中:

pre_path $HOME/bin
add_path /sbin
add_path /usr/sbin
Run Code Online (Sandbox Code Playgroud)

或者指定一个不同的变量:

pre_path $HOME/man MANPATH
pre_path $HOME/share/man MANPATH
add_path /usr/local/man MANPATH
add_path /usr/share/man MANPATH
Run Code Online (Sandbox Code Playgroud)

我在我的 rc 文件中使用此方法,将 pre_paths 放在第一位,然后将 add_paths 放在第二位。它使我的所有路径更改一目了然。另一个好处是这些行足够短,我可以在必要时在一行上添加尾随注释。

由于这些是函数,您可以从命令行交互地使用它们,例如说add_path $(pwd)将当前目录添加到路径中。


Nic*_* M. 11

好的,我想出了以下解决方案,我认为它很优雅(就 shell 语法而言)。它使用 Bash 的数组语法以及一种简洁的方式来连接元素:

paths=(
  /some/dir
  /another/dir
  '/another/dir with spaces in it'
  /yet/another
  /and/another
  /end
)
paths_joined=$( IFS=: ; echo "${paths[*]}" )

PATH=$paths_joined:$PATH
Run Code Online (Sandbox Code Playgroud)

警报!

事实证明,这个解决方案有一个问题:与@terdon 和@Starfish 的解决方案不同,它不会首先检查路径是否已经在 PATH 中。因此,由于我想将此代码放在 ~/.bashrc(而不是 ~/.profile)中,重复的路径将进入 PATH。所以不要使用这个解决方案(除非你把它放在 ~/.profile (或者更好的是 ~/.bash_profile 因为它有 Bash 特定的语法))。


ter*_*don 5

我在我的~/.bashrc. 这是我从旧实验室的系统管理员那里得到的东西,但我认为不是他写的。只需将这些行添加到您的~/.profile~/.bashrc

pathmunge () {
        if ! echo $PATH | /bin/grep -Eq "(^|:)$1($|:)" ; then
           if [ "$2" = "after" ] ; then
              PATH=$PATH:$1
           else
              PATH=$1:$PATH
           fi
        fi
}
Run Code Online (Sandbox Code Playgroud)

这有多种优点:

  • 添加新目录到$PATH很简单:pathmunge /foo/bar;
  • 它避免了重复的条目;
  • 您可以选择是否添加新条目的开始(pathmunge /foo/bar或结束(pathmunge /foo/bar的)之后$PATH

您的 shell 的初始化文件将包含如下内容:

pathmunge /some/dir
pathmunge /another/dir
pathmunge '/another/dir with spaces in it'
pathmunge /yet/another
pathmunge /and/another
pathmunge /end
Run Code Online (Sandbox Code Playgroud)

  • @NiccoloM。没问题,接受你喜欢的。但是要小心海星的方法,它会通过 `eval` 执行任意代码,所以如果你用错误的参数运行它可能会造成一些严重的损害。 (2认同)