以编程方式为查找命令(Bash)构建目录排除列表

时间:2018-07-03 14:41:29

标签: bash shell scripting glob

我有一系列目录要从我的find命令的结果中排除,例如EXCLUDE=("foo" "bar")

我可以像这样从交互式终端运行它:

find . -name 'hvr.yml' -not -path "foo/*" -not -path "bar/*"

所以我试图像这样建立论点:

getServersToCheck() {

    # Build command arguments to exclude given dirs
    local exclude_command="-not -path"
    local excount=${#EXCLUDE[@]}
    for ((i=0;i<excount;i++)); do
        EXCLUDE[i]="${exclude_command} ${EXCLUDE[i]}/*"
    done

    find . -name 'hvr.yml' "${EXCLUDE[@]}"
}

但这会导致find抛出未知谓词错误:'-not -path foo / *'

有没有办法实现这一目标?当我回显该命令时,它看起来是正确的,但是必须有一些bash语法规则导致该命令无法按我期望的那样工作。

更新:

我在路径周围添加了\"以排除,因为我读到globation仅发生在带引号的字符串中。 xtrace显示以下内容:

find . -name hvr.yml -not -path '"foo/*"' -not -path '"bar/*"'

单引号可能是问题

删除\"并使用xtrace运行表明,该globbing正在for循环中应用,导致:

find . -name hvr.yml -not -path "foo/fileinfoo" "foo/somethingelseinfoo" -not -path "bar/*" "bar/fileinbar" "bar/otherfilesinbar"

所以find抱怨把随机路径作为参数给出。

是否可以扩展EXCLUDE数组并将/ *添加到命令中每个元素的末尾?

1 个答案:

答案 0 :(得分:0)

找到了我尝试使用grep实现的替代解决方案:

EXCLUDE=("abc" "def")

getPaths() {
    local exclude_count=${#EXCLUDE[@]}
    if [ $exclude_count -eq 0 ]; then
        find . -name $FILENAME | tr '\n' ' '
        return $?
    fi

    # Concat excluded servers as grep regex
    local regex="(${EXCLUDE[0]}"
    for ((i=1;i<exclude_count;i++)); do
        regex="${regex}|${EXCLUDE[i]}"
    done
    regex="${regex})"

    find . -name $FILENAME | grep -Ev "${regex}" | tr '\n' ' '
    return $?
}
  • 如果exclude为空,则运行常规的find命令。
  • 否则,它将为grep建立一个正则表达式,以过滤掉最终看起来像(abc | def)的示例。