如何使用wget多线程与通配符下载并解决.listing文件冲突
问题描述
我想用wget结合通配符批量下载文件,当前采用多后台实例的方式:
wget -r -nd --no-parent --no-remove-listing $ftpUrl -l1 -A file1*.txt & wget -r -nd --no-parent --no-remove-listing $ftpUrl -l1 -A file2*.txt & wget -r -nd --no-parent --no-remove-listing $ftpUrl -l1 -A file3*.txt &
但每次运行都会下载.listing文件,多实例同时运行时,会出现一个实例在下载该文件、另一个实例要读取它的冲突问题。
同时还有两个疑问:
- 能否锁定
.listing文件,或者让wget不自动下载它(我可以手动完成首次下载)? .listing并非纯URL列表,格式如下,wget是如何读取它的?我尝试用-i .listing(甚至重命名为list.txt后使用-i list.txt)时,会收到URL无效的错误。
drwxr-xr-x 3 4015 4015 16384 Dec 14 21:23 . drwxr-xr-x 4 4015 4015 4096 Dec 14 21:23 .. -rw-r--r-- 1 4015 4015 327 Feb 15 2022 file1-bla.txt -rw-r--r-- 1 4015 4015 10716 Feb 15 2022 file2-bla.txt -rw-r--r-- 1 4015 4015 163 Feb 15 2022 file2-bla.txt
解决办法
1. 规避.listing文件冲突的方案
方案一:让wget自动清理.listing
去掉--no-remove-listing参数,改用--delete-after。wget会下载.listing用于解析目录内容,解析完成后自动删除该文件,从根源避免冲突:
wget -r -nd --no-parent --delete-after $ftpUrl -l1 -A file1*.txt & wget -r -nd --no-parent --delete-after $ftpUrl -l1 -A file2*.txt & wget -r -nd --no-parent --delete-after $ftpUrl -l1 -A file3*.txt &
如果想手动预下载.listing后让wget复用,可添加--use-server-timestamps和--timestamping参数,wget会对比本地与服务器文件的时间戳,一致则直接使用本地文件,不再重新下载:
# 提前手动下载.listing wget $ftpUrl/.listing # 运行批量下载命令 wget -r -nd --no-parent --no-remove-listing --use-server-timestamps --timestamping $ftpUrl -l1 -A file1*.txt & wget -r -nd --no-parent --no-remove-listing --use-server-timestamps --timestamping $ftpUrl -l1 -A file2*.txt &
方案二:给每个实例分配独立的.listing文件
用--dir-prefix参数为每个后台实例指定单独的工作目录,每个实例会在自己的目录里生成.listing,互相不干扰:
mkdir -p dir1 dir2 dir3 wget -r -nd --no-parent --no-remove-listing --dir-prefix=dir1 $ftpUrl -l1 -A file1*.txt & wget -r -nd --no-parent --no-remove-listing --dir-prefix=dir2 $ftpUrl -l1 -A file2*.txt & wget -r -nd --no-parent --no-remove-listing --dir-prefix=dir3 $ftpUrl -l1 -A file3*.txt & # 下载完成后统一移回当前目录 mv dir1/*.txt dir2/*.txt dir3/*.txt ./ rm -r dir1 dir2 dir3
2. .listing文件的解析说明
.listing是FTP服务器返回的类ls -l格式的目录列表,不是纯URL列表,因此无法直接用-i参数读取。wget内部有专门逻辑解析它:跳过开头的.和..目录项,识别出文件条目后,拼接原FTP URL生成完整的下载链接。
如果想手动解析.listing生成可用于-i的URL列表,可用awk提取文件名并拼接:
# 从.listing提取文件名,生成URL列表 awk '/^-/ {print "'$ftpUrl'/"$NF}' .listing > url_list.txt # 用wget批量下载 wget -nd -i url_list.txt
内容的提问来源于stack exchange,提问作者Fulalas
相关产品推荐
相关产品推荐

