télécharger le fichier via http uniquement s'il a été modifié depuis la dernière mise à jour


20

J'ai besoin de télécharger un fichier depuis un serveur HTTP, mais seulement s'il a changé depuis la dernière fois que je l'ai téléchargé (par exemple via l'en- If-Modified-Sincetête). J'ai également besoin d'utiliser un nom personnalisé pour le fichier sur mon disque.

Quel outil puis-je utiliser pour cette tâche sous Linux?


wget -Nne peut pas être utilisé car -Nne peut pas être utilisé avec -O.


Pourquoi ne pas télécharger le fichier puis le renommer?
Julian Knight

.. parce que l'outil doit encore pouvoir vérifier si la ressource HTTP a changé depuis le dernier téléchargement? Ce sera difficile si le fichier a été renommé et n'existe donc plus à l'endroit où l'outil l'attend.
cweiske

Désolé, j'ai précipité ce commentaire, voir ma réponse.
Julian Knight

Réponses:


26

Pensez à utiliser à la curlplace de wget:

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

man curl dit:

-z/ --time-cond <expression de date>

(HTTP / FTP) Demandez un fichier qui a été modifié après l'heure et la date indiquées, ou qui a été modifié avant cette heure. L'expression de date peut être toutes sortes de chaînes de date ou si elle ne correspond à aucune chaîne interne, elle essaie d'obtenir l'heure à partir d'un nom de fichier donné à la place.

Si $filecela ne préexiste pas nécessairement, vous devrez rendre l'utilisation de l' -zindicateur conditionnelle, en utilisant test -e "$file":

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

(Notez que nous ne citons pas l'expansion de $zflag ici, car nous voulons qu'elle soit divisée en 0 ou 2 jetons).

Si votre shell prend en charge les tableaux (par exemple Bash), nous avons une version plus sûre et plus propre:

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

7

Le commutateur wget -Nn'obtient le fichier que s'il a changé, donc une approche possible serait d'utiliser le -Ncommutateur simple qui obtiendra le fichier s'il en a besoin mais le laisse avec le mauvais nom. Créez ensuite un lien dur à l'aide de la ln -Pcommande pour le lier à un "fichier" avec le nom correct. Le fichier lié a les mêmes métadonnées que l'original.

La seule limitation étant que vous ne pouvez pas avoir de liens physiques au-delà des limites du système de fichiers.


À de nombreuses fins, un lien symbolique peut être adéquat - à moins que l'identité d'inode ne soit réellement importante pour le demandeur.
Toby Speight

1
wget est le meilleur outil pour ce travail. Il vérifie l'horodatage ET la taille du fichier, ce qui n'est pas le cas pour Curl (7.38.0). De plus, wget se termine avec non-0 sur 4xx / 5xx, alors que curl ne se soucie pas vraiment des codes serveur par défaut.
schieferstapel

4

Script Python 3.5+ pour la commande 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 (),
))

C'est génial! TIL chain:)
John Oxley

1

Une approche similaire à la « vérification de la date » (avec «curl - time-cond»), serait de télécharger en fonction de la comparaison de taille de fichier, c'est-à-dire de télécharger uniquement si le fichier local a une taille différente de celle du fichier distant .

Il est utile, par exemple, lorsque le processus de téléchargement a échoué au milieu et que le fichier téléchargé local obtient donc une date plus récente que le fichier distant, mais qu'il est en réalité corrompu et qu'un nouveau téléchargement est nécessaire:

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'option "curl -z / --time-cond" (qui a été suggérée dans une autre réponse) ne téléchargera pas le fichier distant dans ce cas (car le fichier local a une date plus récente), mais ce script de " contrôle de taille " le fera!

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.