我编写了一个小型 bash 脚本来查找我的用户中是否存在名为anaconda
或 的目录。但它没有在我的主目录中找到该目录。miniconda
$HOME
miniconda2
我该如何修复这个问题?
if [ -d "$HOME"/"(ana|mini)conda[0-9]?" ]; then
echo "miniconda directory is found in your $HOME"
else
echo "anaconda/miniconda is not found in your $HOME"
fi
PS:如果我有[ -d "$HOME"/miniconda2 ]; then
,那么它会找到 miniconda2 目录,所以我认为错误在于部分"(ana|mini)conda[0-9]?"
我希望脚本具有通用性。对我来说,它是 miniconda2,但对于其他用户来说,它可能是 anaconda2、miniconda3 等等。
答案1
想要做好这件事却出乎意料地困难。
从根本上来说,-d
只会测试一个参数——即使您可以使用正则表达式匹配文件名。
一种方法是将问题反过来,测试目录是否与正则表达式匹配,而不是测试目录是否与正则表达式匹配。换句话说,循环全部使用简单的 shell glob中的目录$HOME
,并根据正则表达式测试每个目录,匹配时中断,最后测试数组是否BASH_REMATCH
非空:
#!/bin/bash
for d in "$HOME"/*/; do
if [[ $d =~ (ana|mini)conda[0-9]? ]]; then
break;
fi
done
if ((${#BASH_REMATCH[@]} > 0)); then
echo "anaconda/miniconda directory is found in your $HOME"
else
echo "anaconda/miniconda is not found in your $HOME"
fi
另一种方法是使用扩展的 shell glob 代替正则表达式,并捕获数组中的任何 glob 匹配项。然后测试数组是否为非空:
#!/bin/bash
shopt -s extglob nullglob
dirs=( "$HOME"/@(ana|mini)conda?([0-9])/ )
if (( ${#dirs[@]} > 0 )); then
echo "anaconda/miniconda directory is found in your $HOME"
else
echo "anaconda/miniconda is not found in your $HOME"
fi
尾随/
确保仅目录匹配;nullglob
防止 shell 在零匹配的情况下返回不匹配的字符串。
要使任一递归,请设置globstar
shell 选项(shopt -s globstar
),然后分别:-
(正则表达式版本):
for d in "$HOME"/**/; do
(扩展的 glob 版本):
dirs=( "$HOME"/**/@(ana|mini)conda?([0-9])/ )
答案2
确实,正如前面提到的,这很棘手。我的方法如下:
- 使用
find
及其正则表达式查找相关目录的能力。 - 让
find
打印x
每个找到的目录 - 将 es存储
x
在字符串中 - 如果字符串非空,则表示找到了其中一个目录。
因此:
xString=$(find $HOME -maxdepth 1 \
-type d \
-regextype egrep \
-regex "$HOME/(ana|mini)conda[0-9]?" \
-printf 'x');
if [ -n "$xString" ]; then
echo "found one of the directories";
else
echo "no match.";
fi
解释:
find $HOME -maxdepth 1
查找下面的所有内容$HOME
,但将搜索限制在一个级别(即:它不会递归到子目录)。-type d
限制搜索d
范围-regextype egrep
告诉find
什么类型的正则表达式我们处理。这是必要的,因为像[0-9]?
和 这样的东西(…|…)
有些特殊,find
默认情况下无法识别它们。-regex "$HOME/(ana|mini)conda[0-9]?"
是实际的 正则表达式我们想要关注-printf 'x'
只打印x
每个事物 满足先前的条件。
答案3
您可以循环遍历要测试的目录名称列表,如果其中一个存在则对其采取行动:
a=0
for i in {ana,mini}conda{,2}; do
if [ -d "$i" ]; then
unset a
break
fi
done
echo "anaconda/miniconda directory is ${a+not }found in your $HOME"
此解决方案显然无法发挥正则表达式的全部功能,但至少在您展示的情况下,shell 通配符和括号扩展是相等的。只要有一个目录存在,循环就会退出,并取消设置先前设置的变量a
。在随后的echo
一行中,参数扩展 ${a+not }
a
如果设置了(=未找到目录),则扩展为无,否则扩展为“不”。
答案4
可能的解决方法是分别搜索 miniconda 和 anaconda,如下所示
if [ -d "$HOME"/miniconda* ] || [ -d "$HOME"/anaconda* ]; then
echo "miniconda directory is found in your $HOME"
else
echo "anaconda/miniconda is not found in your $HOME"
fi
但是如果有人有建议,我想知道为什么我们不能在搜索目录时传递正则表达式。