在您的Makefile中尝试以下操作:
.PHONY: local.dat
local.dat:
[ -e example.gz ] || touch -d '00:00' example.gz
curl -z example.gz -s http://example.org/example.gz -o example.gz
[ -e $@ ] || touch -d 'yesterday 00:00' $@
if [ "$(shell stat --printf '%Y' example.gz)" \
-gt "$(shell stat --printf '%Y' $@)" ] ; then \
zcat example.gz | transmogrify >$@ ; \
fi
truncate -s 0 example.gz
touch -r $@ example.gz
(请注意:这是一个Makefile,因此缩进是制表符,而不是空格。当然\
,在续行上的空格后也没有空格是很重要的-否则,请删除反斜杠转义符并将其变长,几乎不可读的行)
这个GNU make
配方首先检查一个名为example.gz
存在的文件(因为我们将-z
在in中使用它curl
),并touch
在不存在的情况下创建它。触摸会以00:00(当天的凌晨12点)的时间戳创建它。
然后,它使用curl
的-z
(--time-cond
)选项仅example.gz
在自上次下载以来对其进行了修改的情况下进行下载。 -z
可以给出实际的日期表达式或文件名。如果给定文件名,它将使用文件的修改时间作为时间条件。
之后,如果local.dat
不存在,则使用touch
,确保使用早于的时间戳创建它example.gz
。这是必需的,因为local.dat
必须存在下stat
一条命令才能使用它的mtime时间戳。
然后,如果example.gz
时间戳晚于local.dat
,它将通过管道传递example.gz
到transmogrify
并将输出重定向到local.dat
。
最后,它执行簿记和清理工作:
- 它会截断
example.gz
(因为您只需要保留一个时间戳,而不是整个文件)
touch
es,example.gz
以便它具有与local.dat
.PHONY目标可确保local.dat
始终执行该目标,即使该名称的文件已经存在也是如此。
感谢@Toby Speight在评论中指出我的原始版本不起作用以及原因。
或者,如果您想直接将文件传输到其中transmogrify
而无需先将其下载到文件系统中:
.PHONY: local.dat
local.dat:
[ -e example.gz ] || touch -d '00:00' example.gz
[ -e $@ ] || touch -d 'yesterday 00:00' $@
if [ "$(shell stat --printf '%Y' example.gz)" \
-gt "$(shell stat --printf '%Y' $@)" ] ; then \
curl -z example.gz -s http://example.org/example.gz | transmogrify >$@ ; \
fi
touch -r $@ example.gz
注意:这大部分未经测试,因此可能需要进行一些较小的更改才能使语法完全正确。这里重要的是方法,而不是复制粘贴的简单方法。
数十年来,我一直在使用这种方法的变体(即-添加touch
时间戳文件)make
。它可以正常工作,通常可以避免使用sh编写自己的依赖关系解析代码(尽管我必须在stat --printf %Y
此处执行类似的操作)。
众所周知,这make
是一个很棒的软件编译工具... IMO,它对于系统管理和脚本编写任务也是一个被低估的工具。
-z
当然,该标志假定远程服务器使用If-Modified-Since
标头。不一定是这种情况。根据服务器的设置,您可能需要使用ETag
或通过检查Cache-Control
标头或通过检查单独的校验和文件(例如,如果服务器提供sha1sum
)来执行某些操作。