You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写封装find命令的辅助函数,统一排除指定目录并支持完整的find参数传入

如何编写封装find命令的辅助函数,统一排除指定目录并支持完整的find参数传入

兄弟,我太懂你这种糟心的情况了——多个脚本里重复写排除目录的find逻辑,时间久了各个脚本的排除列表还不一样,维护起来简直头疼!而且find的参数顺序还特别苛刻,路径必须在表达式前面,想同时兼容自定义路径和表达式确实有点绕不过来。不过别慌,咱们用几个shell小技巧就能搞定这个my_find辅助函数,既能统一排除危险目录,又能像原生find一样支持所有参数!

核心思路拆解

要实现这个需求,我们需要解决两个关键问题:

  • 正确分离用户传入的路径参数和表达式参数,确保排除目录的逻辑插入到合适的位置
  • 用find原生的-prune选项跳过危险目录(比事后过滤效率高得多,find会直接跳过这些目录的遍历)
  • 自动处理默认路径,同时避免重复输出(比如用户已经指定-print0或-exec时,不再额外加-print)

完整的辅助函数代码

my_find() {
    # 定义需要排除的危险目录模式(相对于find的起始路径)
    local hazard_conditions="\
        -path '_output' \
        -o -path 'release' \
        -o -path 'target' \
        -o -path '*/third_party/*' \
        -o -path '*/vendor/*' \
    "

    # 分离用户传入的路径参数和表达式参数
    local paths=()
    local exprs=()
    local in_expr=false

    for arg in "$@"; do
        if [[ "$arg" == -* ]]; then
            # 遇到以-开头的参数,开始处理表达式部分
            in_expr=true
            exprs+=("$arg")
        else
            if $in_expr; then
                # 已经进入表达式阶段,后续非-开头的参数是表达式的参数(比如-exec的命令)
                exprs+=("$arg")
            else
                # 还在路径阶段,加入路径列表
                paths+=("$arg")
            fi
        fi
    done

    # 如果用户没传路径,默认使用当前目录
    if [ ${#paths[@]} -eq 0 ]; then
        paths=(.)
    fi

    # 判断用户是否已经指定了输出/动作类参数(避免重复输出)
    local has_action=false
    for e in "${exprs[@]}"; do
        case "$e" in
            -print|-print0|-exec|-ok|-delete|-ls|-fls)
                has_action=true
                break
                ;;
        esac
    done

    # 执行最终的find命令
    if $has_action; then
        find "${paths[@]}" \( $hazard_conditions \) -prune -o "${exprs[@]}"
    else
        find "${paths[@]}" \( $hazard_conditions \) -prune -o "${exprs[@]}" -print
    fi
}

实际使用示例

  1. 默认路径+表达式过滤:

    # 在当前目录下查找所有最近7天修改的.sh脚本,自动跳过危险目录
    my_find -type f -name '*.sh' -mtime -7
    
  2. 指定多路径+动作命令:

    # 在./src和./tests目录下,把所有.md文件复制到./backup/,自动跳过危险目录
    my_find ./src ./tests -name '*.md' -exec cp {} ./backup/ \;
    
  3. 带特殊输出格式:

    # 查找当前目录下的所有.go文件,用null分隔输出(适合xargs -0)
    my_find -type f -name '*.go' -print0
    

注意事项

  • 如果需要调整危险目录列表,直接修改函数里的hazard_conditions即可,所有使用my_find的脚本都会自动同步更新,再也不会出现列表不一致的问题
  • 用-path而不是-wholename是为了保证不管用户指定什么起始路径,排除规则都能生效(比如用户指定./src,-path '_output'会匹配./src/_output)

备注:内容来源于stack exchange,提问作者Tim Hockin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.20 07:29:37