Coba sesuatu seperti ini di Makefile Anda:
.PHONY: local.dat
local.dat:
[ -e example.gz ] || touch -d '00:00' example.gz
curl -z example.gz -s http://example.org/example.gz -o example.gz
[ -e $@ ] || touch -d 'yesterday 00:00' $@
if [ "$(shell stat --printf '%Y' example.gz)" \
-gt "$(shell stat --printf '%Y' $@)" ] ; then \
zcat example.gz | transmogrify >$@ ; \
fi
truncate -s 0 example.gz
touch -r $@ example.gz
(catatan: ini adalah Makefile, jadi indentasi adalah tab, bukan spasi. Tentu saja juga penting bahwa tidak ada spasi setelah \
pada garis kelanjutan - atau singkirkan dari garis miring terbalik dan buat satu panjang, baris yang hampir tidak dapat dibaca)
make
Resep GNU ini pertama-tama memeriksa apakah suatu file yang dipanggil example.gz
ada (karena kita akan menggunakannya dengan -z
in curl
), dan membuatnya dengan touch
jika tidak. Sentuhan menciptakannya dengan cap waktu 00:00 (12:00 hari ini).
Maka menggunakan curl
's -z
( --time-cond
) pilihan untuk hanya men-download example.gz
jika telah dimodifikasi sejak terakhir kali itu didownload. -z
dapat diberikan ekspresi tanggal aktual, atau nama file. Jika diberi nama file, itu akan menggunakan waktu modifikasi file sebagai kondisi waktu.
Setelah itu, jika local.dat
tidak ada, ia membuatnya dengan touch
menggunakan cap waktu yang dijamin lebih tua dari itu example.gz
. Ini diperlukan karena local.dat
harus ada untuk perintah berikutnya yang digunakan stat
untuk mendapatkan cap waktu mtime-nya.
Kemudian, jika example.gz
memiliki timestamp yang lebih baru dari local.dat
, itu menyalurkan example.gz
ke transmogrify
dan mengarahkan output ke local.dat
.
Akhirnya, ia melakukan pembukuan & pembersihan:
- itu memotong
example.gz
(karena Anda hanya perlu menyimpan stempel waktu, dan bukan seluruh file)
touch
es example.gz
sehingga memiliki cap waktu yang sama sepertilocal.dat
Target .PHONY memastikan bahwa local.dat
target selalu dijalankan, bahkan jika file dari nama itu sudah ada.
Terima kasih kepada @Toby Speight karena menunjukkan di komentar bahwa versi asli saya tidak akan berfungsi, dan mengapa.
Sebagai alternatif, jika Anda ingin menyalurkan file secara langsung transmogrify
tanpa mengunduhnya ke sistem file:
.PHONY: local.dat
local.dat:
[ -e example.gz ] || touch -d '00:00' example.gz
[ -e $@ ] || touch -d 'yesterday 00:00' $@
if [ "$(shell stat --printf '%Y' example.gz)" \
-gt "$(shell stat --printf '%Y' $@)" ] ; then \
curl -z example.gz -s http://example.org/example.gz | transmogrify >$@ ; \
fi
touch -r $@ example.gz
CATATAN: ini sebagian besar belum diuji sehingga mungkin memerlukan beberapa perubahan kecil untuk mendapatkan sintaks yang tepat. Yang penting di sini adalah metode, bukan solusi copy-paste kargo-kultus.
Saya telah menggunakan variasi dari metode ini (yaitu touch
fileing timestamp) dengan make
selama beberapa dekade. Ini berfungsi, dan biasanya memungkinkan saya untuk menghindari harus menulis kode resolusi ketergantungan saya sendiri di sh (walaupun saya harus melakukan sesuatu yang mirip dengan di stat --printf %Y
sini).
Semua orang tahu make
adalah alat yang hebat untuk mengkompilasi perangkat lunak ... IMO itu juga alat yang sangat rendah untuk admin sistem dan tugas skrip.
-z
bendera, tentu saja, mengasumsikan bahwa server remote menggunakanIf-Modified-Since
header. Ini mungkin belum tentu demikian. Bergantung pada pengaturan server, Anda mungkin perlu melakukan sesuatu denganETag
, atau dengan memeriksaCache-Control
header, atau dengan memeriksa file checksum yang terpisah (misalnya jika server menyediakan asha1sum
).make
, menggunakancmp
atau sesuatu untuk membandingkan file lama dan baru, danmv newfile oldfile
jika mereka berbeda) . BTW, header-kontrol cache tidak memberi tahu Anda jika file lebih baru dari waktu yang ditentukan. mereka memberi tahu Anda berapa lama admin server ingin Anda membuat cache file yang diberikan untuk - dan sering digunakan oleh droid pemasaran sebagai praktik penghilang cache untuk "meningkatkan" statistik web mereka.ETag
adalah cara lain untuk melakukannya, seperti halnya file checksum yang terpisah. Itu semua tergantung pada bagaimana server diatur. Sebagai contoh, seseorang dapat mengambil cdimage.debian.org/debian-cd/current/amd64/iso-cd/SHA1SUMS dan memeriksa apakah sudah berubah sebelum memutuskan untuk mengambil ISO penuh. ETag melakukan hal yang sama, menggunakan header bukan file terpisah (dan, sepertiIf-Modified-Since
, bergantung pada server HTTP yang mengimplementasikannya).Cache-Control
akan menjadi pilihan terakhir untuk mengunduh file jika tidak ada metode lain yang didukung - itu pasti yang paling tidak akurat karena mencoba untuk memprediksi masa depan.ETag
/If-None-Match
dan checksum lainnya lebih dapat diandalkan daripadaIf-Modified-Since
juga. Bagaimanapun, komentar ini hanya mencoba untuk meletakkan asumsi jawaban (yaitu, yang-z
mengasumsikan dukungan server) - metode dasar harus cukup mudah untuk beradaptasi dengan algoritma pemeriksaan perubahan lainnya.Alternatif lain adalah menggunakan sistem pembangunan yang menggunakan checksum dependensi untuk menentukan apakah akan memicu pembangunan kembali. Saya telah menggunakan trik "sentuh" dengan Gnu Make a lot, tetapi jauh lebih mudah ketika Anda dapat menentukan dependensi dinamis dan ketika file yang tidak berubah tidak memicu pembangunan kembali. Berikut ini contoh menggunakan GoodMake :
sumber
-X HEAD
, manual curl merekomendasikan menggunakan-I
: "(-X) hanya mengubah kata aktual yang digunakan dalam permintaan HTTP, itu tidak mengubah cara curl berperilaku. Jadi misalnya jika Anda ingin membuat permintaan HEAD yang tepat, menggunakan -X HEAD tidak akan cukup. Anda perlu menggunakan opsi -I, - head. "