baixar arquivo via http somente se alterado desde a última atualização

20

Preciso fazer o download de um arquivo de um servidor HTTP, mas apenas se ele tiver sido alterado desde a última vez que o baixei (por exemplo, através do If-Modified-Sincecabeçalho). Também preciso usar um nome personalizado para o arquivo no meu disco.

Que ferramenta posso usar para esta tarefa no linux?


wget -Nnão pode ser usado porque -Nnão pode ser usado com -O.

cweiske
fonte
Por que não baixar o arquivo e , em seguida, renomeá-lo?
Julian Knight
.. porque a ferramenta ainda precisa verificar se o recurso HTTP foi alterado desde o último download? Isso será difícil se o arquivo tiver sido renomeado e, portanto, não existir mais no local em que a ferramenta espera.
Cweiske
Desculpe, apressei esse comentário, veja minha resposta.
Julian Knight

Respostas:

26

Considere usar em curlvez de wget:

curl -o "$file" -z "$file" "$uri"

man curl diz:

-z/ --time-cond <expressão da data>

(HTTP / FTP) Solicite um arquivo que foi modificado posteriormente à data e hora especificadas ou que foi modificado antes dessa hora. A expressão de data pode ter todos os tipos de cadeias de datas ou, se não corresponder a nenhuma interna, tenta obter a hora de um determinado nome de arquivo.

Se $filenão existir necessariamente, você precisará -zcondicionar o uso do sinalizador, usando test -e "$file":

if test -e "$file"
then zflag="-z '$file'"
else zflag=
fi
curl -o "$file" $zflag "$uri"

(Observe que não citamos a expansão $zflagdaqui, pois queremos que ela seja dividida em 0 ou 2 tokens).

Se o seu shell suportar matrizes (por exemplo, Bash), teremos uma versão mais segura e mais limpa:

if test -e "$file"
then zflag=(-z "$file")
else zflag=()
fi
curl -o "$file" "${zflag[@]}" "$uri"
Toby Speight
fonte
7

A opção wget -Nsomente obtém o arquivo se tiver sido alterado, portanto, uma abordagem possível seria usar a -Nopção simples que obterá o arquivo se necessário, mas o deixará com o nome errado. Em seguida, crie um link físico usando o ln -Pcomando para vinculá-lo a um "arquivo" com o nome correto. O arquivo vinculado possui os mesmos metadados que o original.

A única limitação é que você não pode ter links físicos através dos limites do sistema de arquivos.

Julian Knight
fonte
Para muitos propósitos, um link simbólico pode ser adequado - a menos que a identidade do inode realmente importe para o solicitante.
precisa
1
O wget é a melhor ferramenta para este trabalho. Ele verifica o carimbo de data e hora e o tamanho do arquivo, que não ondula (7.38.0). Além disso, o wget termina com não 0 em 4xx / 5xx, enquanto o curl não se importa com códigos de servidor por padrão.
schieferstapel
4

Script Python 3.5+ para encapsular o comando curl:

import argparse
import pathlib

from subprocess import run
from itertools import chain

parser = argparse.ArgumentParser()
parser.add_argument('url')
parser.add_argument('filename', type=pathlib.Path)
args = parser.parse_args()

run(chain(
    ('curl', '-s', args.url),
    ('-o', str(args.filename)),
    ('-z', str(args.filename)) if args.filename.exists() else (),
))
sirex
fonte
Isso é incrível! TIL chain:)
John Oxley
1

Uma abordagem semelhante à " verificação de data " (com "curl --time-cond") seria fazer o download de acordo com a comparação do tamanho do arquivo, ou seja, fazer o download apenas se o arquivo local tiver um tamanho diferente do arquivo remoto .

É útil, por exemplo, quando o processo de download falha no meio e, portanto, o arquivo baixado local obtém uma data mais recente que o arquivo remoto, mas na verdade está corrompido e é necessário fazer o download novamente:

local_file_size=$([[ -f ${FILE_NAME} ]] && wc -c < ${FILE_NAME} || echo "0")
remote_file_size=$(curl -sI ${FILE_URL} | awk '/Content-Length/ { print $2 }' | tr -d '\r' )

if [[ "$local_file_size" -ne "$remote_file_size" ]]; then
    curl -o ${FILE_NAME} ${FILE_URL}
fi

A opção "curl -z / --time-cond" (sugerida em outra resposta) não fará o download do arquivo remoto nesse caso (porque o arquivo local tem uma data mais recente), mas esse script de " verificação de tamanho " fará!

Noam Manos
fonte