scarica il file via http solo se modificato dall'ultimo aggiornamento


20

Devo scaricare un file da un server HTTP, ma solo se è cambiato dall'ultima volta che l'ho scaricato (ad es. Tramite l' If-Modified-Sinceintestazione). Devo anche usare un nome personalizzato per il file sul mio disco.

Quale strumento posso usare per questa attività su Linux?


wget -Nnon può essere utilizzato perché -Nnon può essere utilizzato con -O.


Perché non scaricare il file e quindi rinominarlo?
Julian Knight,

.. perché lo strumento deve ancora essere in grado di verificare se la risorsa HTTP è cambiata dall'ultimo download? Questo sarà difficile se il file è stato rinominato e quindi non esiste più nel luogo in cui lo strumento lo prevede.
cweiske,

Scusa, ho affrettato quel commento, vedi la mia risposta.
Julian Knight,

Risposte:


26

Prendi in considerazione l'utilizzo curlinvece di wget:

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

man curl dice:

-z/ --time-cond <espressione data>

(HTTP / FTP) Richiedere un file che è stato modificato dopo la data e l'ora specificate o uno che è stato modificato prima di tale orario. L'espressione della data può essere qualsiasi tipo di stringa di date o, se non corrisponde a nessuna interna, cerca invece di ottenere l'ora da un determinato nome di file.

Se $filenon necessariamente preesistente, dovrai subordinare l'uso del -zflag, usando test -e "$file":

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

(Nota che non citiamo l'espansione di $zflagqui, poiché vogliamo che subisca una divisione in 0 o 2 token).

Se la tua shell supporta array (ad esempio Bash), abbiamo una versione più sicura e pulita:

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

7

L'opzione wget -Nottiene il file solo se è cambiato, quindi un possibile approccio sarebbe quello di utilizzare il semplice -Nswitch che otterrà il file se necessario, ma lo lascia con il nome sbagliato. Quindi creare un collegamento reale utilizzando il ln -Pcomando per collegarlo a un "file" con il nome corretto. Il file collegato ha gli stessi metadati dell'originale.

L'unica limitazione è che non è possibile avere hard link attraverso i confini del file system.


Per molti scopi, un collegamento simbolico può essere adeguato, a meno che l'identità dell'inode non sia realmente importante per il richiedente.
Toby Speight,

1
wget è lo strumento migliore per questo lavoro. Controlla il timestamp E la dimensione del file, che non arriccia (7.38.0). Inoltre, wget termina con un valore diverso da 0 su 4xx / 5xx, mentre per impostazione predefinita curl non si preoccupa davvero dei codici server.
schieferstapel,

4

Script Python 3.5+ per il comando wrapping 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 (),
))

Questo e spettacolare! TIL chain:)
John Oxley,

1

Un approccio simile al " controllo della data " (con "curl --time-cond") sarebbe quello di scaricare in base al confronto delle dimensioni del file, ovvero scaricare solo se il file locale ha una dimensione diversa rispetto al file remoto .

È utile, ad esempio, quando il processo di download non è riuscito nel mezzo , e quindi il file scaricato locale ottiene una data più recente rispetto al file remoto, ma in realtà è danneggiato e è necessario il nuovo download:

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

L'opzione "curl -z / --time-cond" (che è stata suggerita in un'altra risposta) non scaricherà il file remoto in questo caso (perché il file locale ha una data più recente), ma lo script " controllo dimensioni " lo farà!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.