Tente algo assim no seu 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
(nota: este é um Makefile, portanto, os recuos são tabulações, não espaços. é claro. Também é importante que não haja espaços após as \
linhas de continuação - alternativamente, elimine as escapes da barra invertida e faça uma longa, linha quase ilegível)
Esta make
receita GNU primeiro verifica se example.gz
existe um arquivo chamado (porque vamos usá-lo com -z
in curl
) e o cria touch
se não existir. O toque o cria com um registro de data e hora de 00:00 (00:00 do dia atual).
Em seguida, ele usa curl
a opção 's -z
( --time-cond
) para fazer o download apenas example.gz
se tiver sido modificado desde a última vez em que foi baixado. -z
pode receber uma expressão de data real ou um nome de arquivo. Se receber um nome de arquivo, ele usará a hora da modificação do arquivo como condição de hora.
Depois disso, se local.dat
não existir, ele será criado touch
, usando um carimbo de data / hora garantido para ser mais antigo que o de example.gz
. Isso é necessário porque local.dat
deve existir para o próximo comando usar stat
para obter o registro de data e hora do mtime.
Então, se example.gz
tem um timestamp mais recente do que local.dat
, ele tubos example.gz
em transmogrify
e redireciona a saída para local.dat
.
Finalmente, ele faz as coisas de contabilidade e limpeza:
- trunca
example.gz
(porque você só precisa manter um carimbo de data e hora, e não o arquivo inteiro)
touch
es example.gz
para que ele tenha o mesmo timestamp quelocal.dat
O destino .PHONY garante que o local.dat
destino seja sempre executado, mesmo se o arquivo com esse nome já existir.
Agradeço a @Toby Speight por apontar nos comentários que minha versão original não funcionaria e por quê.
Como alternativa, se você quiser canalizar o arquivo diretamente transmogrify
sem fazer o download primeiro no sistema de arquivos:
.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
NOTA: como a maioria não é testada, pode ser necessário fazer pequenas alterações para obter a sintaxe exatamente correta. O importante aqui é o método, não uma solução de culto à carga de copiar e colar.
Eu tenho usado variações desse método (por exemplo, em touch
um arquivo de carimbo de data / hora) make
há décadas. Funciona e geralmente me permite evitar escrever meu próprio código de resolução de dependência no sh (embora eu tenha tido que fazer algo semelhante stat --printf %Y
aqui).
Todo mundo sabe que make
é uma ótima ferramenta para compilar software ... O IMO também é uma ferramenta muito subestimada para tarefas de administração e script do sistema.
-z
sinalização, é claro, assume que o servidor remoto usaIf-Modified-Since
cabeçalhos. Isso pode não ser necessariamente o caso. Dependendo da configuração do servidor, você pode precisar fazer algo comETag
, ou verificandoCache-Control
cabeçalhos ou verificando um arquivo de soma de verificação separado (por exemplo, se o servidor fornecer asha1sum
).make
, usecmp
ou algo para comparar arquivos antigos e novos emv newfile oldfile
se forem diferentes) . Aliás, os cabeçalhos de controle de cache não informam se o arquivo é mais recente que um determinado momento. eles informam por quanto tempo os administradores do servidor querem que você armazene em cache um determinado arquivo - e são freqüentemente usados por dróides de marketing como uma prática de impedir o cache para "melhorar" suas estatísticas da web.ETag
é outra maneira de fazer isso, assim como um arquivo de soma de verificação separado. Tudo depende de como o servidor está configurado. Por exemplo, é possível buscar cdimage.debian.org/debian-cd/current/amd64/iso-cd/SHA1SUMS e verificar se ele mudou antes de decidir buscar a ISO completa. ETag faz a mesma coisa, usando um cabeçalho em vez de um arquivo separado (e, comoIf-Modified-Since
, depende do servidor HTTP que o implementa).Cache-Control
seria uma opção de último recurso, exceto baixar o arquivo, se nenhum outro método for suportado - certamente é o menos preciso, pois ele tenta prever o futuro.ETag
/If-None-Match
e outras somas de verificação são mais confiáveis do queIf-Modified-Since
também. De qualquer forma, esses comentários apenas tentam expor as suposições da resposta (ou seja, que-z
assume o suporte do servidor) - o método básico deve ser bastante fácil de se adaptar a outros algoritmos de verificação de alterações.Outra alternativa é usar um sistema de construção que use somas de verificação de dependência para determinar se é necessário acionar reconstruções. Eu usei o truque do "toque" com o Gnu Make, mas é muito mais simples quando você pode especificar dependências dinâmicas e quando arquivos que não são alterados não acionam reconstruções. Aqui está um exemplo usando o GoodMake :
fonte
-X HEAD
, a página de manual do curl recomenda o uso de-I
: "(-X) altera apenas a palavra real usada na solicitação HTTP, não altera a maneira como o curl se comporta. Portanto, por exemplo, se você deseja fazer uma solicitação HEAD adequada, use -X HEAD não será suficiente. Você precisa usar a opção -I, - head. "