检测用户的路径是否包含特定目录

epo*_*olf 46 bash shell path

/bin/bash,我如何检测用户的$ PATH变量中是否有特定的目录?

例如

if [ -p "$HOME/bin" ]; then
  echo "Your path is missing ~/bin, you might want to add it."
else
  echo "Your path is correctly set"
fi
Run Code Online (Sandbox Code Playgroud)

Gor*_*son 129

使用grep是过度杀伤,如果您正在搜索包含RE元字符的任何内容,可能会造成麻烦.使用bash的内置[[命令可以很好地解决这个问题:

if [[ ":$PATH:" == *":$HOME/bin:"* ]]; then
  echo "Your path is correctly set"
else
  echo "Your path is missing ~/bin, you might want to add it."
fi
Run Code Online (Sandbox Code Playgroud)

请注意,在$ PATH的扩展和搜索路径之前添加冒号解决了子串匹配问题; 双引号路径避免了元字符的麻烦.

  • @MestreLion 即使那样它也应该正常工作;这就是为什么需要在 `":$PATH:"` 中添加额外的冒号。 (4认同)
  • @bobbogo 需要在 `=` 的右侧引用引号,以防目录包含任何 glob 元字符(这很不寻常,但可能)。它对左侧没有影响,但我更喜欢在任何地方都双引号变量(除非有特定的理由不这样做),而不是试图跟踪所有关于安全或不安全的奇怪规则将它们放在一边(例如此处比较的右侧)。 (3认同)
  • 无需在“[[”和“]]”内引用。那里不会发生分词和路径名扩展。 (2认同)

Pau*_*ce. 11

以下是没有的方法grep:

if [[ $PATH == ?(*:)$HOME/bin?(:*) ]]
Run Code Online (Sandbox Code Playgroud)

这里的关键是使用?()构造使冒号和通配符可选.此表单中的元字符应该没有任何问题,但是如果要包含引号,这就是它们的位置:

if [[ "$PATH" == ?(*:)"$HOME/bin"?(:*) ]]
Run Code Online (Sandbox Code Playgroud)

这是使用match运算符(=~)执行此操作的另一种方法,因此语法更像grep是:

if [[ "$PATH" =~ (^|:)"${HOME}/bin"(:|$) ]]
Run Code Online (Sandbox Code Playgroud)

  • `?(:*)` 是一个 [extended glob](https://mywiki.wooledge.org/glob#extglob) 模式,需要在大多数平台上单独显式启用 (`shopt -s extglob`)。 (2认同)

tri*_*eee 7

There is absolutely no need to use external utilities like grep for this. Here is what I have been using, which should be portable back to even legacy versions of the Bourne shell.

case :$PATH: # notice colons around the value
  in *:$HOME/bin:*) ;; # do nothing, it's there
     *) echo "$HOME/bin not in $PATH" >&2;;
esac
Run Code Online (Sandbox Code Playgroud)


Ada*_*kin 5

一些非常简单和天真的东西:

echo "$PATH"|grep -q whatever && echo "found it"
Run Code Online (Sandbox Code Playgroud)

无论你在寻找什么.而不是&&你可以放入$?变量或使用适当的if语句.

限制包括:

  • 以上将匹配较大路径的子串(尝试匹配"bin",它可能会找到它,尽管事实上"bin"不在你的路径中,/ bin和/ usr/bin是)
  • 以上不会自动扩展像〜的快捷方式

或使用perl one-liner:

perl -e 'exit(!(grep(m{^/usr/bin$},split(":", $ENV{PATH}))) > 0)' && echo "found it"
Run Code Online (Sandbox Code Playgroud)

它仍有限制,它不会进行任何shell扩展,但如果子字符串匹配则不会失败.(以上匹配" /usr/bin",如果不清楚的话).

  • 很好,有人在3.5年后对此进行了贬低.并没有发表评论.瘸. (3认同)
  • 像JasonWoof的答案中一样,匹配到行首/结尾和冒号可解决您的子字符串匹配限制。波浪号扩展并不是一个普遍的问题,因为大多数人都允许在分配时对其进行扩展(例如`PATH =“〜/ bin:$ PATH”`),但可以在需要时进行替换。 (2认同)