ดาวน์โหลดไฟล์ผ่าน http เฉพาะเมื่อมีการเปลี่ยนแปลงนับตั้งแต่การอัพเดทครั้งล่าสุด


20

ฉันจำเป็นต้องดาวน์โหลดไฟล์จากเซิร์ฟเวอร์ HTTP แต่เฉพาะเมื่อมีการเปลี่ยนแปลงตั้งแต่ครั้งสุดท้ายที่ฉันดาวน์โหลดไฟล์ (เช่นผ่านIf-Modified-Sinceส่วนหัว) ฉันต้องใช้ชื่อที่กำหนดเองสำหรับไฟล์บนดิสก์ของฉัน

ฉันสามารถใช้เครื่องมือใดสำหรับงานนี้บน linux


wget -Nไม่สามารถนำมาใช้เพราะไม่สามารถใช้ร่วมกับ-N-O


ทำไมไม่ดาวน์โหลดไฟล์แล้วเปลี่ยนชื่อมัน?
Julian Knight

.. เพราะเครื่องมือยังต้องสามารถตรวจสอบว่าทรัพยากร HTTP เปลี่ยนไปจากการดาวน์โหลดครั้งล่าสุดหรือไม่ สิ่งนี้จะยากหากไฟล์ถูกเปลี่ยนชื่อและไม่มีอยู่ในตำแหน่งที่เครื่องมือคาดว่าจะเป็นอีกต่อไป
cweiske

ขออภัยฉันรีบแสดงความคิดเห็นนั้นดูคำตอบของฉัน
Julian Knight

คำตอบ:


26

พิจารณาใช้curlแทนwget:

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

man curl พูดว่า:

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

(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คำสั่งเพื่อลิงก์ไปยัง "ไฟล์" ด้วยชื่อที่ถูกต้อง ไฟล์ที่เชื่อมโยงมีข้อมูลเมตาเดียวกันกับต้นฉบับ

ข้อ จำกัด เพียงอย่างเดียวคือคุณไม่สามารถมีฮาร์ดลิงก์ข้ามขอบเขตระบบไฟล์ได้


สำหรับหลาย ๆ วัตถุประสงค์ลิงก์สัญลักษณ์อาจเพียงพอ - ยกเว้นว่าข้อมูลเฉพาะตัวของไอโหนดนั้นสำคัญสำหรับผู้ถาม
Toby Speight

1
wget เป็นเครื่องมือที่ดีกว่าสำหรับงานนี้ มันตรวจสอบการประทับเวลาและขนาดไฟล์ซึ่ง curl (7.38.0) ไม่ได้ นอกจากนี้ wget ยุติด้วย non-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 (),
))

นี่มันเจ๋งมาก! TIL chain:)
John Oxley

1

วิธีการที่คล้ายกับ " วันที่เช็ค " (กับ "ขด --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" (ที่แนะนำในคำตอบอื่น) จะไม่ดาวน์โหลดไฟล์ระยะไกลในกรณีนี้ (ทำให้ไฟล์ในเครื่องมีวันที่ใหม่กว่า) แต่สคริปต์ "การตรวจสอบขนาด " จะทำเช่นนี้!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.