我有一个包含源文件(*.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