检测用户的path中是否有特定的目录
使用/bin/bash
,我将如何检测用户是否在其$ PATHvariables中有特定的目录?
例如
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
一些非常简单和天真的事情:
echo "$PATH"|grep -q whatever && echo "found it"
无论你在寻找什么。 而不是&&
你可以把$?
变成一个variables或使用一个适当的if
语句。
限制包括:
- 以上将匹配较大path的子串(尽pipe“bin”不在你的path中,/ bin和/ usr / bin都是这样的),尝试在“bin”上匹配,它可能会find它。
- 以上不会自动扩展〜的快捷方式
或者使用perl单行程式:
perl -e 'exit(!(grep(m{^/usr/bin$},split(":", $ENV{PATH}))) > 0)' && echo "found it"
这仍然有限制,它不会做任何shell扩展,但它不会失败,如果一个子string匹配。 (如果不清楚,以上匹配“ /usr/bin
”)。
使用grep
是矫枉过正的,如果你正在寻找包含RE元字符的东西,会造成麻烦。 这个问题可以用bash的builtin很好的解决[[
command:
if [[ ":$PATH:" == *":$HOME/bin:"* ]]; then ...
请注意,在$ PATH扩展和searchpath之前添加冒号解决了子string匹配问题; 双引号的path避免了元字符的麻烦。
这里是如何做到这一点,没有grep
:
if [[ $PATH == ?(*:)$HOME/bin?(:*) ]]
这里的关键是使用?()
构造使冒号和通配符可选。 在这种forms中元字符不应该有任何问题,但是如果你想包含引号,这是他们去的地方:
if [[ "$PATH" == ?(*:)"$HOME/bin"?(:*) ]]
这是另一种使用匹配运算符( =~
)的方法,所以语法更像grep
:
if [[ "$PATH" =~ (^|:)"${HOME}/bin"(:|$) ]]
$PATH
是由:
分隔的string列表:
描述目录列表。 目录是由/
分隔的string列表。 两个不同的string可能指向相同的目录(如$HOME
和~
,或/usr/local/bin
和/usr/local/bin/
)。 所以我们必须修正我们想要比较/检查的规则。 我build议比较/检查整个string,而不是物理目录,但删除重复和尾随/
。
首先删除$PATH
中的重复和尾随:
echo $ PATH | tr -s / | sed's / \ /:/:/ g; s /:/ \ n / g'
现在假设$d
包含你想检查的目录。 然后通过pipe道命令来检查$PATH
$d
。
echo $ PATH | tr -s / | sed的/ \ /:/:/ g; s /:/ \ n / g'| grep -q“^ $ d $”|| 回声“缺less$ d”
我编写了下面的shell函数来报告目录是否在当前PATH
列出。 这个函数是POSIX兼容的,并且可以在Dash和Bash等兼容的shell中运行(不依赖于Bash特有的特性)。
它包括将相对path转换为绝对path的function。 它使用readlink
或realpath
实用工具,但如果提供的目录没有..
或其他链接作为其path的组件,则不需要这些工具。 除此之外,该function不需要shell程序。
# Check that the specified directory exists – and is in the PATH. is_dir_in_path() { if [ -z "${1:-}" ]; then printf "The path to a directory must be provided as an argument.\n" >&2 return 1 fi # Check that the specified path is a directory that exists. if ! [ -d "$1" ]; then printf "Error: '%s' is not a directory.\n" "$1" >&2 return 1 fi # Use absolute path for the directory if a relative path was specified. if command -v readlink >/dev/null ; then dir="$(readlink -f "$1")" elif command -v realpath >/dev/null ; then dir="$(realpath "$1")" else case "$1" in /*) # The path of the provided directory is already absolute. dir="$1" ;; *) # Prepend the path of the current directory. dir="$PWD/$1" ;; esac printf "Warning: neither 'readlink' nor 'realpath' are available.\n" printf "Ensure that the specified directory does not contain '..' in its path.\n" fi # Check that dir is in the user's PATH. case ":$PATH:" in *:"$dir":*) printf "'%s' is in the PATH.\n" "$dir" return 0 ;; *) printf "'%s' is not in the PATH.\n" "$dir" return 1 ;; esac }
使用:$PATH:
的部分:$PATH:
如果所需的path是PATH
的第一个或最后一个条目,则确保该模式也匹配。 这个聪明的窍门是基于Unix和Linux上Glenn Jackman的这个回答 。