使用/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
答案 0 :(得分:118)
使用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
请注意,在$ PATH扩展和搜索路径之前添加冒号可以解决子字符串匹配问题;双引号路径避免了元字符的麻烦。
答案 1 :(得分:10)
以下是没有grep
的方法:
if [[ $PATH == ?(*:)$HOME/bin?(:*) ]]
这里的关键是使用?()
构造使冒号和通配符可选。这种形式的元字符不应该有任何问题,但如果你想包含引号,这就是它们的去处:
if [[ "$PATH" == ?(*:)"$HOME/bin"?(:*) ]]
这是另一种使用匹配运算符(=~
)的方法,因此语法更像grep
:
if [[ "$PATH" =~ (^|:)"${HOME}/bin"(:|$) ]]
答案 2 :(得分:5)
一些非常简单和天真的东西:
echo "$PATH"|grep -q whatever && echo "found it"
无论你在寻找什么。您可以将&&
放入变量或使用正确的$?
语句,而不是if
。
限制包括:
或使用perl one-liner:
perl -e 'exit(!(grep(m{^/usr/bin$},split(":", $ENV{PATH}))) > 0)' && echo "found it"
它仍有限制,它不会进行任何shell扩展,但如果子字符串匹配则不会失败。 (以上情况与“/usr/bin
”匹配,如果不清楚的话。)
答案 3 :(得分:4)
绝对不需要像grep
那样使用外部实用程序。以下是我一直在使用的内容,它应该可以移植到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
答案 4 :(得分:1)
我编写了以下shell函数来报告目录是否列在当前PATH
中。此函数与POSIX兼容,将在兼容的shell(如Dash和Bash)中运行(不依赖于Bash特定的功能)。
它包含将相对路径转换为绝对路径的功能。它使用readlink
或realpath
实用程序,但如果提供的目录没有..
或其他链接作为其路径的组件,则不需要这些工具。除此之外,该函数不需要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
的部分可确保模式也匹配。这个聪明的技巧基于this answer by Glenn Jackman on Unix & Linux。
答案 5 :(得分:1)
这是一个纯bash实现,由于部分匹配而不会出现假阳性。
if [[ $PATH =~ ^/usr/sbin:|:/usr/sbin:|:/usr/sbin$ ]] ; then
do stuff
fi
这是怎么回事? =〜运算符使用从3.0版开始在bash中提供的regex模式支持。正在检查三种模式,由正则表达式的OR运算符|
分隔。
所有三个子模式都相对相似,但是它们的区别对于避免部分匹配很重要。
在正则表达式中,^
匹配到行的开头,$
匹配到行的结尾。如所写,第一个模式仅在其寻找的路径是$ PATH中的第一个值时才评估为true。如果要查找的路径是$ PATH中的最后一个值,则第三个模式将评估为true。当第二种模式在其他值之间找到它要寻找的路径时,它将评估为true,因为它正在寻找$ PATH变量使用的定界符:
到要搜索的路径的任一侧。
答案 6 :(得分:0)
$PATH
是由:
分隔的字符串列表,用于描述目录列表。目录是由/
分隔的字符串列表。两个不同的字符串可能指向同一目录(例如$HOME
和~
,或/usr/local/bin
和/usr/local/bin/
)。所以我们必须修改我们想要比较/检查的规则。我建议比较/检查整个字符串,而不是物理目录,但删除重复和尾随/
。
首先从/
删除重复和尾随$PATH
:
echo $PATH | tr -s / | sed 's/\/:/:/g;s/:/\n/g'
现在假设$d
包含您要检查的目录。然后通过管道上一个命令检查$d
中的$PATH
。
echo $PATH | tr -s / | sed 's/\/:/:/g;s/:/\n/g' | grep -q "^$d$" || echo "missing $d"
答案 7 :(得分:0)
这是一种蛮力方法,但它在所有情况下都有效,除非路径条目包含冒号。除了外壳,没有其他程序被使用。
~/.ssh/known_hosts