завантажуйте файл через http, лише якщо його змінено з моменту останнього оновлення


20

Мені потрібно завантажити файл з HTTP-сервера, але тільки якщо він змінився з моменту останнього завантаження (наприклад, через If-Modified-Sinceзаголовок). Мені також потрібно використовувати власне ім'я для файлу на своєму диску.

Який інструмент я можу використовувати для цього завдання в Linux?


wget -Nне може бути використаний, тому що -Nне може бути використаний з -O.


Чому б не завантажити файл , а потім перейменувати його?
Лицар Джуліана

.. тому що інструменту ще потрібно мати можливість перевірити, чи змінився ресурс HTTP з моменту останнього завантаження? Це буде важко, якщо файл буде перейменований і, таким чином, більше не існує в тому місці, де інструмент очікує його.
cweiske

Вибачте, я поспішив на цей коментар, дивіться мою відповідь.
Юліанський лицар

Відповіді:


26

Подумайте про використання curlзамість wget:

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

man curl каже:

-z/ --time-cond <дата виразу>

(HTTP / FTP) Попросіть файл, який було змінено пізніше зазначеного часу та дати, або файл, який був змінений до цього часу. Вираз дати може бути різного роду рядками дати або, якщо він не відповідає жодним внутрішнім, він намагається отримати час із заданого імені файлу.

Якщо $fileце не обов'язково існує, вам потрібно буде -zумовно використовувати прапор, використовуючи test -e "$file":

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

(Зверніть увагу, що ми не цитуємо розширення $zflagтут, оскільки хочемо, щоб воно було розбито на 0 або 2 лексеми).

Якщо ваша оболонка підтримує масиви (наприклад, Bash), у нас є більш безпечна і чиста версія:

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

7

Перемикач wget -Nотримує файл лише в тому випадку, якщо він змінився, тому можливим підходом було б використовувати простий -Nперемикач, який отримає файл, якщо йому потрібно, але залишить його з неправильним ім'ям. Потім створіть жорстке посилання за допомогою ln -Pкоманди, щоб прив'язати його до "файлу" з правильним ім'ям. Зв'язаний файл має ті самі метадані, що й оригінал.

Єдине обмеження полягає в тому, що ви не можете мати жорсткі посилання через межі файлової системи.


Для багатьох цілей символічне посилання може бути адекватним - якщо тільки ідентифікація inode насправді не має значення для запитувача.
Toby Speight

1
wget - кращий інструмент для цієї роботи. Він перевіряє часову позначку І розмір файлу, якого не згортає (7.38.0). Крім того, wget закінчується не-0 на 4xx / 5xx, тоді як curl насправді не хвилює серверні коди за замовчуванням.
schieferstapel

4

Сценарій Python 3.5+ для обертання команди 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 (),
))

Це круто! ТІЛ chain:)
Джон Окслі

1

Аналогічний підхід до " перевірки дати " (з "curl - time-cond") передбачає завантаження відповідно до порівняння розміру файлу, тобто завантажувати лише в тому випадку, якщо локальний файл має інший розмір, ніж віддалений файл .

Це корисно, наприклад, коли процес завантаження не вдався посередині , і, таким чином, локальний завантажений файл отримує новішу дату, ніж віддалений файл, але він фактично пошкоджений, і потрібно повторне завантаження:

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

Параметр "curl -z / --time-cond" (що було запропоновано в іншій відповіді) не завантажуватиме віддалений файл у цьому випадку (тому що в локальному файлі є більш нова дата), але цей сценарій " перевірки розміру " буде!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.