実際のソースファイルのみを見つけるように検索出力をフィルタリングしますか?

実際のソースファイルのみを見つけるように検索出力をフィルタリングしますか?

ソースファイル(* .c)を含む大規模なディレクトリツリーがあり、その一部(すべてではない)は実際に次のものを生成する前処理によって生成されます。どの.cからどの.qc ファイル。

多くの場合、これらのファイルを使用して作業を実行する必要がありますが、最終的なソースファイルのみを使用する必要があります。どの.qc、言うことはできません。どの.c(しかしそうでない場合それは何ですか.qc だとしたら、本当に見てみたいと思いそれは何ですか。氏)。

次のように起動します。

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。これらのパス名のバッチに対して短いシェルスクリプトが呼び出されます。シェルスクリプトは与えられた各パス名をテストし、それをに変更し、変更されたパス.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

関連情報