我正在用 wget 下载一些测量数据,格式如下
http://www.somewhere.com/sub-somewhere052/image0001.jpg
http://www.somewhere.com/sub-somewhere052/file0001.txt
取决于
http://www.somewhere.com/sub-somewhere052/image0099.jpg
http://www.somewhere.com/sub-somewhere052/file0099.txt
问题是,这两个数字在不同的测试中会发生变化(这是测试052),并且每个测试都有未知的文件数量(我事先不知道)。但是,它们都具有相同的名称(它们不被称为某处,当然),这是众所周知的。
我怎样才能让 wget “穿过” sub-somewhere001/image0001.jpg 到 imagexxxx.jpg(其中 xxxx 未知),直到到达不再存在的一个文件,然后移动到(filexxxx.txt 之后)somewhere002/... 等等?
简单来说,就是如何应对“一直到没有了为止”的情况?
答案1
从中man wget
,你可以看到它使用了通常的 Unix 返回值约定 - 0 表示没有错误,其他任何值都是错误。如果你不期望其他类型的错误(例如网络故障或类似情况),即你期望如果它没有下载任何内容就意味着没有文件,则可以使用如下方法:
get_tf_simulated() {
t=$1
if [ $t -lt 3 ]; then
f=$3
s=$((2 * $t))
if [ $f -lt $s ]; then
return 0
fi
fi
return 1
}
get_tf_real() {
tp=$2
fp=$4
inf=$5
ext=$6
# Get http://example.com/test<test number>/<image or file><file number>.<jpg or txt>
wget -Otest$tp_file$fp_$inf.$ext http://example.com/test$tp/$inf$fp.$ext
}
get_tf() {
echo --- Getting $*
get_tf_simulated $*
#get_tf_real $*
}
get_all() {
get_tf $t $tp $f $fp image jpg
ret_val=$?
if [ $ret_val -ne 0 ]; then
return $ret_val
fi
get_tf $t $tp $f $fp file txt
}
for t in {1..999}; do
tp=`printf %3.3d $t`
got_one=no
for f in {1..9999}; do
fp=`printf %4.4d $f`
get_all $t $tp $f $fp
if [ $? -ne 0 ]; then
echo Failed, going next
break
fi
got_one=yes
done
if [ $got_one == 'no' ]; then
echo Nothing more
break
fi
done
取消注释函数中的正确行get_all
。目前,它将模拟它,输出将如下所示(前提是您将上述内容保存到mkt.sh
):
$ ./mkt.sh
--- Getting 1 001 1 0001 image jpg
--- Getting 1 001 1 0001 file txt
--- Getting 1 001 2 0002 image jpg
Failed, going next
--- Getting 2 002 1 0001 image jpg
--- Getting 2 002 1 0001 file txt
--- Getting 2 002 2 0002 image jpg
--- Getting 2 002 2 0002 file txt
--- Getting 2 002 3 0003 image jpg
--- Getting 2 002 3 0003 file txt
--- Getting 2 002 4 0004 image jpg
Failed, going next
--- Getting 3 003 1 0001 image jpg
Failed, going next
Nothing more
请注意,我没有测试这个wget
,但您可以使用它来测试几个文件:
wget -Otest$tp_file$fp_$inf.$ext http://example.com/test$tp/$inf$fp.$ext; echo $?
只需根据需要替换$tp
、$fp
和$inf
,$ext
例如与您给出的类似示例:
wget -Otest052_file0001_file.txt http://www.example.com/sub-somewhere052/file0001.txt; echo $?
这应该会响应8
404,来自man wget
:
8 Server issued an error response.
如果这有效,那么脚本就应该可以工作,希望那一行没有拼写错误。:)
答案2
如果网站返回404
响应,wget
则将变量设置$?
为非零值(具体为 8,但谁在乎呢)。您可以对此进行测试。
我觉得 bash 相当令人困惑,所以这里有一个 Python (2.7.2) 版本。它应该可以工作,但如果没有方便的网站,我无法直接测试。它取决于服务器是否返回正确的 404 响应。
#! /usr/bin/python
basepath = "http://www.somewhere.com/sub-somewhere"
imgpre = "/image"
imgpost = ".jpg"
txtpre = "/txt"
txtpost = ".txt"
import os
import urllib2
directorynum = 1
filenum = 1
while True:
pathdir = basepath + str(directorynum).zfill(3)
if filenum == 1:
try:
os.makedirs(pathdir[7:])
except OSError, e:
print "Error creating directory: " + e.strerror
pathimg = pathdir + imgpre + str(filenum).zfill(4) + imgpost
pathtxt = pathdir + txtpre + str(filenum).zfill(4) + txtpost
try:
print "Getting " + pathimg
resp = respimg = urllib2.urlopen(pathimg)
with open(pathimg[7:], "wb") as f:
f.write(respimg.read())
print "Getting " + pathtxt
resp = resptxt = urllib2.urlopen(pathtxt)
with open(pathtxt[7:], "w") as f:
f.write(resptxt.read())
filenum += 1
continue
except urllib2.HTTPError, e:
if e.code == 404:
print "Error: 404"
print "Got " + str(filenum - 1) + " from directory " + str(directorynum) + ", incrementing directory."
directorynum += 1
filenum = 1
continue
else:
print "An unexpected error (" + resp.code + resp.msg + ") has occurred."
break
它也可以在 Windows 上正常运行(只需删除#! /usr/bin/python
并保存为.py
文件,但必须安装 Python 解释器)