curl/wget下载技巧:断点续传、API交互、批量下载
curl 和 wget 是 Linux 最常用的两个命令行下载工具,各有侧重:wget 擅长文件下载(递归、镜像、断点续传),curl 擅长 API 交互(POST、认证、调试、cookie 会话)。本文覆盖两者的断点续传、批量下载、认证鉴权、限速重试,以及 NCBI/Ensembl/ENA/GEO 下载场景实操。
实测环境:Debian 12,curl 8.11.0,wget 1.24.5。
1. 基础速览——什么时候用谁
| 场景 | 工具 | 理由 |
|---|---|---|
| 下载单个大文件,需要断点续传 | wget | 默认支持 -c,更稳健 |
| 调用 REST API(NCBI E-utilities等) | curl | POST/GET灵活,JSON处理方便 |
| 递归下载整个目录(FTP) | wget | -r -np 原生支持 |
| 调试 HTTP 请求头 | curl | -v 输出详细到每个header |
| 需要 Cookie 认证的网站 | curl | -b -c 管理 Cookie 文件 |
| 后台静默下载 | wget | -b 后台模式,日志写到 wget-log |
| 限速下载(不打扰实验室其他人) | wget | --limit-rate 简单可靠 |
我的原则:下载文件用 wget,调接口用 curl。
2. wget 实操——下载文件的不二之选
2.1 断点续传——最核心的功能
# 基础断点续传wget -c https://ftp.ensembl.org/pub/release-113/fasta/homo_sapiens/dna/Homo_sapiens.GRCh38.dna.primary_assembly.fa.gz
# -c = --continue,检测本地已有部分,从断点继续# 如果你的网络不稳定,养成加 -c 的习惯-c 的工作原理:wget 先检查本地文件大小 ,然后向服务器发送 Range: bytes=S_{local}- 请求头,服务器返回 206 Partial Content,从断点传输。整个过程对用户透明:
断点续传能把下载时间从「重头来」变成「只补缺的部分」。
2.2 后台下载 + 日志
# 后台下载,日志写到 wget-logwget -b -c -o download.log https://example.com/huge.fastq.gz
# -b = --background,立刻返回终端# -o 指定日志文件(注意小写 -o 是日志,-O 是输出文件名)# tail -f download.log 可以实时查看进度2.3 限速——文明下载
# 限速 5MB/s,不影响实验室其他人wget -c --limit-rate=5m https://example.com/large.bam
# 单位:k=KB/s, m=MB/s# 建议白天 2-5m,晚上适当放开2.4 递归下载——扒整个目录
# 递归下载 Ensembl 某个物种的所有 FASTAwget -r -np -nH --cut-dirs=3 -A "*.fa.gz" \ ftp://ftp.ensembl.org/pub/release-113/fasta/homo_sapiens/dna/
# 参数拆解:# -r → 递归下载# -np → 不追溯父目录# -nH → 不创建主机名目录# --cut-dirs=3 → 跳过前3级目录# -A "*.fa.gz" → 只下载 .fa.gz 文件警告:递归下载前先用 --spider 试探一下目录结构和文件大小,别一上来就把整个 FTP 站点扒下来。
# 先侦查wget --spider -r -np ftp://ftp.ensembl.org/pub/release-113/fasta/homo_sapiens/dna/ 2>&1 | grep '^--'2.5 批量下载——从 URL 列表
# urls.txt 每行一个URLcat > urls.txt << 'EOF'https://example.com/sample1_R1.fastq.gzhttps://example.com/sample1_R2.fastq.gzhttps://example.com/sample2_R1.fastq.gzhttps://example.com/sample2_R2.fastq.gzEOF
# 批量下载wget -c -i urls.txt
# -i = --input-file,从文件读取URL列表# 结合 -c 实现批量断点续传2.6 重试机制——网络不稳的救星
# 最多重试20次,每次间隔30秒wget -c -t 20 --retry-connrefused --waitretry=30 \ https://unstable-server.example.com/data.fastq.gz
# -t 20 → 重试20次(0或inf=无限)# --retry-connrefused → 连接被拒也重试# --waitretry=30 → 重试等待30秒3. curl 实操——API 交互利器
3.1 基础下载
# curl 默认输出到 stdout,需要用 -o 指定输出文件curl -o genome.fa.gz https://ftp.ensembl.org/pub/release-113/fasta/homo_sapiens/dna/Homo_sapiens.GRCh38.dna.primary_assembly.fa.gz
# -O(大写)使用远程文件名curl -O https://example.com/file.fastq.gz
# 断点续传用 -C -curl -C - -O https://example.com/huge.fastq.gz# -C - 自动检测已有大小并从断点续传3.2 NCBI E-utilities API——生信最常见的 curl 场景
# 1. 搜索 GEO 数据集curl -s "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=gds&term=RNA-seq+human+liver&retmax=5" \ | grep '<Id>' | sed 's/<[^>]*>//g' | tr -d ' '
# 2. 获取 SRA Run 信息curl -s "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=sra&id=SRR12345678&rettype=runinfo&retmode=text"
# 3. 获取 FASTQ 下载链接(ENA API)curl -s "https://www.ebi.ac.uk/ena/portal/api/filereport?accession=SRR12345678&result=read_run&fields=fastq_ftp,fastq_aspera&format=tsv"
# -s = --silent,隐藏进度条,适合管道处理3.3 POST 请求——提交数据和表单
# NCBI Batch Entrez 用 POST 提交多个 IDcurl -s -X POST \ -d "id=NM_001301717, NM_001301718&db=nuccore&rettype=fasta&retmode=text" \ "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi" \ -o sequences.fasta
# -X POST → 指定POST方法# -d "..." → POST数据体3.4 添加请求头——模仿浏览器
# 有些服务器需要特定的 User-Agentcurl -H "User-Agent: Mozilla/5.0" \ -H "Accept: application/json" \ -o data.json \ https://api.example.com/v1/datasets
# -H 添加自定义请求头,可多次使用3.5 Cookie 管理——登录认证场景
# 1. 保存 Cookiecurl -c cookies.txt -d "username=xxx&password=yyy" \ https://example.com/login
# 2. 用 Cookie 下载需要登录的文件curl -b cookies.txt -o private_data.tar.gz \ https://example.com/protected/download
# -c 保存cookie,-b 加载cookie3.6 调试利器——看请求全貌
# -v 输出完整请求/响应头curl -v https://api.example.com/data 2>&1 | head -30
# -I 只获取响应头(不下载内容)curl -I https://ftp.ensembl.org/pub/release-113/fasta/homo_sapiens/dna/Homo_sapiens.GRCh38.dna.primary_assembly.fa.gz# 输出 Content-Length 等信息,提前知道文件大小
# -w 输出格式化信息curl -s -o /dev/null -w "HTTP Status: %{http_code}\nSize: %{size_download}\nTime: %{time_total}s\n" \ https://ftp.ensembl.org/pub/release-113/fasta/homo_sapiens/dna/Homo_sapiens.GRCh38.dna.primary_assembly.fa.gz3.7 限速和超时
# 限速 5MB/s,超时 300 秒curl --limit-rate 5M --max-time 300 -C - -O https://example.com/huge.fastq.gz
# --max-time → 整个操作的总超时时间# --connect-timeout → 连接阶段的超时(默认可能很长)4. wget vs curl——性能差异
理论上下载单个文件时两者的速度取决于 TCP 窗口和网络状况,没有本质差异:
其中 是带宽上限, 是 TCP 拥塞窗口, 是往返时间。实测中 wget 默认 buffer 稍大,curl 管道处理更灵活。
5. 生信典型场景速查表
| 场景 | 推荐命令 |
|---|---|
| 下载 Ensembl 参考基因组 | wget -c ftp://.../Homo_sapiens.GRCh38.dna.primary_assembly.fa.gz |
| 批量下载 GEO FASTQ | wget -c -i sra_urls.txt |
| 查询 NCBI 序列 | curl -s "https://eutils.../efetch.fcgi?..." |
| 下载需要认证的数据 | curl -b cookies.txt -c cookies.txt -L -O URL |
| 递归下载 GFF 注释目录 | wget -r -np -A "*.gff3.gz" ftp://... |
| 检查远程文件大小 | curl -sI URL | grep -i content-length |
6. 踩坑记录
坑1:wget 不加 -c 每次从头下载。 wget 默认行为:如果目标文件已存在,会在文件名后加 .1 而不是续传。养成常用操作:凡是 wget 必加 -c。
坑2:curl 的 -O 和 -o 搞混。 -O(大写)使用远程文件名,-o(小写)指定本地文件名。我曾在循环里用错,结果所有文件都覆盖成了同一个。
坑3:wget 递归默认不限制深度。 不加 -l(level)的话,wget 默认递归深度为 5。在大型 FTP 站点上这可能下载几万个文件。用 -l 2 限制深度或用 --spider 先侦查。
坑4:curl POST 数据中的特殊字符。 -d 参数里的 & 和 ? 等特殊字符可能被 shell 解释。要么用单引号,要么用 --data-urlencode 逐个参数传。
坑5:FTP 被动模式连接失败。 有些 FTP 服务器不支持被动模式,wget 默认被动模式被防火墙挡住时加 --no-passive-ftp 切主动模式。或者用 --ftp-user 和 --ftp-password 指定认证。
坑6:wget 的 -o 和 -O 混淆。 wget -o log.txt 是把日志写到 log.txt,wget -O output.txt 是把下载内容保存为 output.txt。这个拼写相近,错了排查半天。
坑7:curl 下载 HTTPS 证书错误。 内网服务器或自签名证书会报 SSL 错误。临时绕过用 -k(--insecure),但生产环境严禁此操作,正确做法是安装对应 CA 证书。
本文于 2025-02-14 在 Debian 12 上实测。
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!