在bash中查找目录路径时如何传递正则表达式?

Jen*_*nny 14 command-line bash scripts

我编写了一个小的 bash 脚本来查找名为anacondaminiconda在我的用户中的目录$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
Run Code Online (Sandbox Code Playgroud)

PS:如果我有[ -d "$HOME"/miniconda2 ]; then,那么它会找到 miniconda2 目录,所以我认为错误在于部分"(ana|mini)conda[0-9]?"

我希望脚本是通用的。对我来说,它是 miniconda2,但对于其他一些用户,它可能是 anaconda2、miniconda3 等等。

ste*_*ver 13

这是一件非常棘手的事情,要做得很好。

从根本上说,-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
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用扩展的 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
Run Code Online (Sandbox Code Playgroud)

尾随/确保仅匹配目录;该nullglob防止了壳从在零个一致的情况下返回的不匹配的字符串。


要进行递归,请分别设置globstarshell 选项 ( shopt -s globstar),然后分别:-

  • (正则表达式版本): for d in "$HOME"/**/; do

  • (扩展全局版本): dirs=( "$HOME"/**/@(ana|mini)conda?([0-9])/ )

  • 你甚至不需要 extglob 是你使用大括号扩展(这会生成所有可能的匹配名称):`~/{ana,mini}conda{0..9}*/` (2认同)

Per*_*uck 9

事实上,正如已经提到的,这很棘手。我的方法如下:

  • 使用find及其正则表达式功能来查找有问题的目录。
  • 让我们为每个找到的目录find打印一个x
  • xes存储在字符串中
  • 如果字符串非空,则找到目录之一。

因此:

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
Run Code Online (Sandbox Code Playgroud)

解释:

  • find $HOME -maxdepth 1查找下面的所有内容,$HOME 但将搜索限制在一个级别(即:它不会递归到子目录中)。
  • -type d将搜索限制为仅d搜索
  • -regextype egrep告诉我们处理find什么类型的正则表达式。这是必需的,因为像[0-9]?和 之(…|…)类的东西有些特殊,find 并且默认情况下无法识别它们。
  • -regex "$HOME/(ana|mini)conda[0-9]?"是我们要查找的实际 正则表达式
  • -printf 'x'x为 满足先前条件的每个事物打印一个。

  • @Jenny 您在复制它时可能打错了,因为它对我来说很好用。`-printf` 不是命令,而是 `find` 的参数。这就是上一行末尾的反斜杠的作用。 (3认同)