如何编写目标文件和源文件具有相同扩展名的Makefile?

时间:2012-04-05 23:50:41

标签: makefile

我有一些每小时获得的数据文件。它们的文件名看起来像:

20120101-00.raw
20120101-01.raw
...
YYYYMMDD-HH.raw

我必须将每小时文件聚合到每日,每天到每月等。汇总脚本的语法如下:

aggregate output-file input-file1 input-file2 ...

聚合模式是:

20120101-[0-2][0-9].raw -> 20120101.raw
201201[0-3][0-9].raw -> 201201.raw
etc.

我正在尝试编写Makefile来自动化进程,但我完全陷入困境 - 我不知道如何处理扩展问题 - 源文件和目标文件具有相同的扩展名。我用:

$(shell find . -type f | grep -e "\.raw1$$" | cut -c 8 | sort -u )

找到我必须生成的文件。

2 个答案:

答案 0 :(得分:1)

如果我为此编写了一个脚本,它将读取.raw文件名列表,对列表进行排序,对于每个文件名,通过删除最后两位数字来创建缩短的名称,如果此缩短的名称与前一个缩短的名称相同,将完整文件名添加到要聚合的列表中,如果缩短的名称与先前缩短的名称不同,则根据添加到列表的最后一个条目创建输出文件名,如果输出文件已存在且比新的更新添加到列表中的最后一个条目不执行任何操作,因为它已经是最新的,否则使用输出文件名和输入文件列表运行aggregate命令。

要使用该脚本,首先使用所有每小时文件运行它,然后使用所有每日文件再次运行它(如果需要,可以使用所有月度文件再次运行以生成年度文件。)

概述的脚本有一些限制:

  1. 一次只能给出一种文件的列表(例如每小时,每日)
  2. 要聚合的每个组中的所有文件都需要位于同一目录中,或者初始排序需要仅使用filename的basename(而不是directory)部分作为排序键。
  3. 如果这些是在脚本运行时可能正在更新的日志文件,则可能会丢失在运行aggregate命令时记录的数据。这是由于输出文件上的时间戳(用于确定它是否相对于输入文件是最新的)是时间聚合完成,而不是它何时开始。解决方法是在开始聚合之前触摸时间戳文件(基于输出文件名),并使用timestamp文件而不是output-file来确定输出文件是否是最新的。

答案 1 :(得分:0)

我同意Oli Charlesworth的观点,Make不是这项工作的最佳工具 - 我会使用Perl脚本。但是如果你想使用Make,它就可以完成。这是一个使用sed调用的非常可怕的黑客攻击。它可以收紧一点,但我是为了可读性。

FILES := $(shell ls *-??.raw)

DAYS :=   $(sort $(shell ls *-??.raw | sed 's/\(........\).*/\1.raw/'))
MONTHS := $(sort $(shell ls *-??.raw | sed 's/\(......\).*/\1.raw/'))
YEARS :=  $(sort $(shell ls *-??.raw | sed 's/\(....\).*/\1.raw/'))

all.raw: $(YEARS)
    aggregate $@ $^

$(YEARS): %.raw : $(MONTHS)
    aggregate $@ $(filter $*%, $^)

$(MONTHS): %.raw : $(DAYS)
    aggregate $@ $(filter $*%, $^)

$(DAYS): %.raw :
    aggregate $@ $(filter $*%, $(FILES))