Попробуйте что-то подобное в вашем 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
(потому что мы собираемся использовать его с -z
in curl
), и создает его с помощью, touch
если это не так. Прикосновение создает его с отметкой времени 00:00 (12:00 текущего дня).
Затем он использует опцию curl
s -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
).