Попробуйте что-то подобное в вашем 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, поэтому отступы - это табуляции, а не пробелы. Конечно. Также важно, чтобы после \строк продолжения не было пробелов - альтернативно избавьтесь от escape-косых черт и сделайте его одним длинным, почти нечитаемая строка)
Этот makeрецепт GNU сначала проверяет, существует ли файл с именем example.gz(потому что мы собираемся использовать его с -zin curl), и создает его с помощью, touchесли это не так. Прикосновение создает его с отметкой времени 00:00 (12:00 текущего дня).
Затем он использует опцию curls -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Если 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
ПРИМЕЧАНИЕ: это в основном не проверено, поэтому могут потребоваться некоторые незначительные изменения, чтобы получить правильный синтаксис. Здесь важен метод, а не решение копи-пасты Cargo-Cult.
Я использую варианты этого метода (например, touchфайл временной метки) в makeтечение десятилетий. Это работает, и, как правило, позволяет мне избежать написания собственного кода разрешения зависимостей в sh (хотя я должен был сделать что-то подобное stat --printf %Yздесь).
Все знают, makeчто это отличный инструмент для компиляции программного обеспечения ... IMO, он также очень недооцененный инструмент для задач системного администратора и сценариев.
-zФлаг, конечно, предполагает , что удаленный сервер используетIf-Modified-Sinceзаголовки. Это не обязательно так. В зависимости от настроек сервера, вам может потребоваться что-то сделатьETag, либо путем проверкиCache-Controlзаголовков, либо путем проверки отдельного файла контрольной суммы (например, если сервер предоставляет asha1sum).