【问题标题】:Build Directory Exclusion List Programmatically for Find Command (Bash)以编程方式为查找命令(Bash)构建目录排除列表
【发布时间】:2018-12-11 22:20:01
【问题描述】:

我有一组目录要从我的 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 语法规则导致它无法按我的预期工作。

更新:

我在排除路径周围添加了\",因为我读到只有带引号的字符串才会发生通配。 xtrace 显示如下:

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

单引号可能是问题

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

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

因此 find 抱怨将随机路径作为参数给出。

有没有办法扩展 EXCLUDE 数组并将 /* 添加到命令中每个元素的末尾?

【问题讨论】:

    标签: bash shell scripting glob


    【解决方案1】:

    找到了一个替代解决方案,可以通过使用 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) 的内容。

    【讨论】:

      猜你喜欢
      • 2015-06-27
      • 2019-10-08
      • 2011-12-29
      • 2018-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-27
      • 2011-09-28
      相关资源
      最近更新 更多