过滤查找输出以仅查找真正的源文件?

过滤查找输出以仅查找真正的源文件?

我有一个包含源文件(*.c)的大目录树,其中一些(但不是全部)实际上是通过预处理生成的,该预处理生成任何.c 来自 a任何.qc 文件。

通常,我发现自己需要对这些文件做一些事情,但只有最终的源文件——也就是说,如果有任何.qc,看没有意义任何.c(但如果没有那是什么.qc 那么我确实需要看看那是什么。C)。

从这样的事情开始:

find data-utils -name '*.qc' -o -name '*.c' | xargs grep SMS_GEN

假设 find 的输出的一部分是:

data-utils/whatever.c
data-utils/whatsit.c
data-utils/whatever.qc

是否有一些现有的工具可以用来过滤查找的输出,这样我就不会通过任何.c 到 xargs (或查找后的任何内容)。也就是说,上面的过滤结果应该是:

data-utils/whatsit.c
data-utils/whatever.qc

或者我需要从头开始写一些东西吗?

答案1

查找带有文件名后缀的文件,但如果存在此类文件,则.c返回相应文件的路径名:.qc

find server/data-utils -type f -name '*.c' -exec sh -c '
    for pathname do
        if [ -f "${pathname%.c}.qc" ]; then
            printf "%s\n" "${pathname%.c}.qc"
        else
            printf "%s\n" "$pathname"
        fi
    done' sh {} +

这将查找搜索路径中或server/data-utils搜索路径下名称以.c.对于批量的这些路径名,将调用一个简短的 shell 脚本。 shell 脚本测试每个给定的路径名​​,并将其.c替换为.qc,如果修改后的路径名引用现有的常规文件(或指向该文件的符号链接),则将其打印出来。否则,将打印原始路径名。

有关的:


只是上面的一个变体干燥原则应用:

find server/data-utils -type f -name '*.c' -exec sh -c '
    for pathname do
        qc_pathname=${pathname%.c}.qc

        if [ -f "$qc_pathname" ]; then
            out=$qc_pathname
        else
            out=$pathname
        fi

        printf "%s\n" "$out"
    done' sh {} +

...或者甚至只是

find server/data-utils -type f -name '*.c' -exec sh -c '
    for pathname do
        qc_pathname=${pathname%.c}.qc
        [ -f "$qc_pathname" ] && pathname=$qc_pathname
        printf "%s\n" "$pathname"
    done' sh {} +

答案2

我想出了一个 awk 脚本来完成这项工作。它的效率不是特别高,O(n^2),但它的优点是不重新排序(未过滤的)行。

function supercedes ( a, b ) {
        suffixa=match(a, /\.[^/.]*$/);
        suffixb=match(b, /\.[^/.]*$/);
        if ((suffixa == 0) || (suffixa != suffixb)) return 0;
        if (substr(a,1,suffixa) != substr(b,1,suffixb)) return 0;
        return (substr(a,suffixa) == A) && (substr(b,suffixb) == B);
}
BEGIN { n = 0; }
{ item[n++] = $0; }
END {
        for (i = 0; i < n; ++i) {
                show = 1;
                for (j = 0; j < n; ++j) {
                        if (j != i) {
                                if (supercedes(item[i], item[j])) {
                                        show = 0;
                                        break;
                                }
                        }
                }
                if (show) print item[i];
        }
}

示例用法:

find server/data-utils -name '*.qc' -o -name '*.c' | \
    awk -f filter.awk -vA=.c -vB=.qc

相关内容