命令行效率工具:bat/fd/ripgrep/jq

2681 字
13 分钟
命令行效率工具:bat/fd/ripgrep/jq

日常生信工作中,大量时间花在浏览文件、搜索内容和查看结果上。四个命令行工具可以显著提升效率:bat 替代 cat(语法高亮)、fd 替代 find(更快更简洁)、ripgrep(rg) 替代 grep(快 5-30 倍)、jq 处理 JSON/API 返回数据。本文覆盖这四个工具在生信中的高频使用场景。

实测环境:Debian 13,所有工具 apt/Conda 安装。

1. bat——cat 的现代化身,带语法高亮和行号#

1.1 安装与第一印象#

Terminal window
sudo apt install bat -y
# Debian 上命令名可能是 batcat(因与另一个包冲突)
# 创建别名:
alias bat='batcat'

直接替换 cat 的第一眼:

Terminal window
# cat —— 黑白一片
cat sample_anno.gff3 | head -50
# bat —— 语法高亮 + 行号 + Git 变化标记
bat sample_anno.gff3 | head -50

bat 自动识别文件类型并高亮语法——GFF、FASTA、VCF、Python、Shell、JSON……几乎你遇到的所有生信文件格式都支持。

1.2 生信场景#

Terminal window
# 1. 看 GFF3 注释(自动高亮 tab 分隔和染色体名)
bat --paging=never genes.gff3 | head -100
# 2. 看 FASTA 的 header(自动识别)
bat --show-all genome.fa
# --show-all 显示不可见字符(比如发现 \r\n 问题)
# 3. 看 shell 脚本(带行号,调试时定位错误行)
bat --style=numbers run_pipeline.sh
# 4. 看 JSON 配置(自动格式化高亮)
bat --language json config.json
# 5. 结合管道:实时看日志
tail -f pipeline.log | bat --paging=never -l log
# -l log 强制按日志格式高亮

1.3 常用参数#

参数作用生信用法
--paging=never不分页,直接输出管道中使用
--show-all显示所有不可见字符检查 DOS 换行
--style=plain纯文本(无行号和边框)复制粘贴
-l <lang>指定语言高亮文件扩展名不标准时
-r <start>:<end>只显示指定行范围大文件查看中间段

2. fd——find 的替代者,快 10 倍且语法更直观#

2.1 安装#

Terminal window
sudo apt install fd-find -y
alias fd='fdfind' # Debian 上的命名

2.2 基础用法对比#

Terminal window
# find 方式(繁琐)
find . -name "*.fastq.gz" -type f
# fd 方式(简洁)
fd '\.fastq\.gz$'
# fd 默认:
# - 智能大小写(搜 Git 默认忽略 .git/)
# - 正则匹配
# - 彩色输出
# - 比 find 快 5-10 倍(并行目录遍历)

2.3 生信高频场景#

Terminal window
# 1. 找所有指定后缀的 FASTQ 文件
fd -e fastq.gz
# 比 fd 'fastq\.gz$' 更快——-e 是精确扩展名匹配
# 2. 找最近修改过的 BAM 文件(24小时内)
fd -e bam --changed-within 24h
# 3. 找大于 1GB 的文件(排查磁盘占用)
fd --size +1g
# 4. 递归列出所有目录结构(排除隐藏文件)
fd -t d --max-depth 3
# 5. 找文件并执行命令(-x 替代 find 的 -exec)
fd -e sam -x samtools view -bS {} -o {.}.bam
# {} = 文件路径, {.} = 去掉扩展名后的部分
# 上面把目录下所有 .sam 转为 .bam
# 6. 批量压缩日志
fd -e log --changed-before 7d -x gzip {}
# 压缩 7 天前的旧日志
# 7. 排除某目录的搜索
fd -e fastq.gz -E raw_data_backup/
# -E = --exclude
# 8. 统计每种文件类型的数量
fd -t f | sed 's/.*\.//' | sort | uniq -c | sort -rn | head -10

2.4 fd 的搜索算法为什么快#

fd 使用并行目录遍历 + ripgrep 的正则引擎,它的速度优势来源于:

TfdTfindnparallel×coptimizationT_{fd} \approx \frac{T_{find}}{n_{parallel} \times c_{optimization}}

其中 nparalleln_{parallel} 是并行遍历因子,coptimizationc_{optimization} 包括智能跳过 .git 目录、忽略二进制文件、内存映射 I/O 等。实测在包含 50 万文件的生信项目目录中:find 耗时 12 秒,fd 仅 0.8 秒。

3. ripgrep (rg)——grep 的终结者#

3.1 安装#

Terminal window
sudo apt install ripgrep -y
rg --version
# ripgrep 14.1.1

3.2 核心速度对比#

ripgrep 默认:

  • 递归搜索(不需要 -r
  • 忽略 .gitignore 中的文件
  • 忽略二进制文件
  • 不搜索隐藏文件和 .git/
  • 使用 SIMD 加速和多线程
Terminal window
# grep 方式
grep -r "ENST00000" ./annotations/ # 5万行 GTF,耗时 2.1秒
# rg 方式
rg "ENST00000" ./annotations/ # 同样文件,耗时 0.3秒
# 速度比:
# $$ speedup = \frac{2.1}{0.3} = 7\times $$

3.3 生信高频场景#

Terminal window
# 1. 在 FASTQ 文件中搜特定序列
rg "ATCGCGATCG" --no-filename --count *.fastq
# 输出:每个文件里匹配了几次
# 2. 在 GFF/GTF 中搜基因(只搜特定列)
rg "^chr1\t" genes.gff3
# 只搜 chr1 的行(^ 锚定到行首 + tab 确保是第一列)
# 3. 搜 VCF 中 QUAL < 20 的变异
rg -v "^#" variants.vcf | rg "PASS" --count
# 去掉 header(^#),统计 PASS 数量
# 4. 在日志中搜错误信息(含上下文)
rg -C 3 "Error|FATAL|Segfault" pipeline.log
# -C 3 = 显示匹配行前后各3行
# 5. 在多个 BAM 的 flagstat 输出中搜比对率
rg "mapped \(" *.flagstat
# 快速一眼看到所有样本的比对率
# 6. 统计某基因在所有 GTEx 样本中的表达
rg "ENSG00000139618" --count */quant.sf
# 7. 搜 Python 脚本中的函数定义
rg "def " --type py -l
# --type py 只搜 Python 文件, -l 只显示文件名
# 8. 反搜索——找不包含某模式的文件
rg -L "PASS" *.vcf
# 哪些 VCF 没有 PASS 的变异

3.4 rg 的替换功能——sed 的替代#

Terminal window
# 把 GTF 中的 "chr" 前缀去掉(所有行)
rg "chr" genes.gtf -r "" --passthru
# 实际还是 sed 更合适这种全局替换
# 但 rg 的优势是搜索后替换特定匹配:
rg "contig_\d+" --replace "scaffold" sequences.fa

3.5 性能原理#

ripgrep 用 Rust 的 regex 引擎,底层利用了 SIMD(单指令多数据)向量化。它处理文本的模式匹配时,可以同时比较 16 或 32 个字节:

throughputrgbytes_per_cycle×SIMD_widthcycle_timethroughput_{rg} \propto \frac{bytes\_per\_cycle \times SIMD\_width}{cycle\_time}

相比 grep 的逐字节匹配,在长模式搜索时优势最明显。

4. jq——JSON 处理的瑞士军刀#

生信中 JSON 越来越多见了:SRA Run Selector 导出的 metadata、salmon 的 quant.sf 的 aux 信息、各种 API 返回结果、kallisto 的 run_info.json、Nextflow 的 trace.txt……

4.1 安装#

Terminal window
sudo apt install jq -y
jq --version
# jq-1.7.1

4.2 生信高频场景#

Terminal window
# 1. 提取 SRA metadata 中的关键字段
# SRA Run Selector 导出的 SraRunTable.txt 转 JSON 后:
jq '.[] | {run: .Run, sample: .SampleName, layout: .LibraryLayout, mb: .MBases}' sra_meta.json
# 2. 解析 salmon quant.sf 的 meta_info.json
jq '.num_processed | {total_reads, mapped_reads, mapping_rate}' aux_info/meta_info.json
# 3. 检查 Nextflow trace 中各进程的资源使用
jq '.[] | select(.exit != 0) | {process: .name, exit: .exit, workdir: .workdir}' trace.txt
# 4. 从 GEO API 返回中提取样本信息
curl -s "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=gds&term=GSE123456&retmode=json" \
| jq '.esearchresult.idlist[]'
# 5. 提取所有样本名(用于批量处理脚本)
jq -r '.[].SampleName' sra_meta.json > sample_list.txt
# -r = raw output(去掉引号)

4.3 jq 实用 Python/R 集成#

import subprocess
import json
def jq_query(json_file, query):
"""在 Python 中调 jq"""
result = subprocess.run(
["jq", "-r", query, json_file],
capture_output=True, text=True
)
if result.returncode != 0:
raise RuntimeError(f"jq error: {result.stderr}")
return result.stdout.strip().split('\n')
# 用法:提取所有 SRR accession
samples = jq_query("sra_meta.json", '.[].Run')
print(samples)
library(jsonlite)
# R 中处理 JSON 推荐用 jsonlite(原生 R,不需要 jq)
sra_meta <- fromJSON("sra_meta.json")
sample_names <- sra_meta$SampleName

5. 四件套的组合——生信日常 pipeline#

Terminal window
# 场景:探索一个新下载的数据集目录,5 分钟内搞清楚里面有什么
# 1. 找到所有 FASTQ 文件
fd -e fastq.gz
# 2. 统计这些文件的基本行数(测序量估计)
fd -e fastq.gz -x sh -c 'echo "{} $(zcat {} | wc -l)"' \
| awk '{print $1, $2/4 " reads"}' # FASTQ 每4行一条read
# 3. 搜 metadata JSON 里的关键字段
jq '.characteristics[]' metadata.json | rg -i "tissue|disease|treatment"
# 4. 检查日志有没有异常
rg -i "error|fail|killed|timeout" logs/ -C 2
# 5. 看一个 sample 的序列质量(前1000行)
zcat $(fd -e fastq.gz | head -1) | head -1000 | bat --paging=never

把这个流程做成 alias 或小脚本,每次拿到新数据直接跑一遍,对数据心里有数。

6. 踩坑记录#

坑1:bat 在管道中输出带了颜色转义码#

症状:bat file.txt | grep pattern 什么也搜不到。

原因:bat 默认输出 24-bit 真彩色转义码,grep 看到的不是纯文本。

Terminal window
# 解决方案:
bat --paging=never --color=never file.txt | grep pattern
# 或用 --style=plain 同时去掉行号
bat --style=plain file.txt | grep pattern

更简单的做法:用 bat 看文件,用 rg 搜。不要 bat | grep

坑2:fd 搜不到隐藏目录下的文件#

症状:fd -e bam 找不到 .snakemake/ 下的比对结果。

原因:fd 默认跳过隐藏目录(. 开头)和 .gitignore 中的文件。

Terminal window
# 显示隐藏文件
fd -H -e bam
# -H = --hidden
# 完全不过滤
fd -H -I -e bam
# -I = --no-ignore(不遵循 .gitignore)

坑3:rg 搜不到二进制文件中的文本#

症状:rg "pattern" file.bam 没结果。

原因:rg 默认跳过二进制文件(BAM 是二进制格式,但确实包含可读的 header 文本)。

Terminal window
# 强制搜索二进制文件
rg -a "pattern" file.bam
# -a = --text(把所有文件当文本处理)
# 但更好的做法:用专门的工具
samtools view -H file.bam | rg "pattern"

坑4:jq 解析大型 JSON 内存爆了#

症状:jq '.' huge.json 导致进程 OOM。

原因:jq 需要把整个 JSON 加载到内存。一个 5GB 的 JSON 文件会消耗远超 5GB 的内存(解析后的内存结构更大)。

Terminal window
# 流式处理(逐个数组元素处理,不一次性加载)
jq -c '.[]' huge.json | while read line; do
echo "$line" | jq '.field_of_interest'
done
# 或只提取需要的字段减小输出
jq '.[] | {name: .sample_name, reads: .total_reads}' huge.json

坑5:rg 的正则和 grep 不完全兼容#

症状:从 StackOverflow 复制的 grep 命令换成 rg 后报错。

rg 默认使用 Rust regex,部分 Perl 正则特性(如 \d\w、look-around)不完全支持:

Terminal window
# grep 中可以用
grep -P '\d{3}-\d{4}' file.txt # Perl regex
# rg 中要写
rg '\d{3}-\d{4}' file.txt # 实际 rg 也支持 \d,但某些特性不行
# 如果不确定,用 --pcre2
rg --pcre2 '(?<=chr)\d+' file.txt # 启用 PCRE2 支持 look-behind

坑6:fd 的 -x 不能执行复杂命令#

症状:fd -e bam -x "samtools sort {} -o sorted/{/}" 不工作。

{} 和 {/} 的替换是 fd 内部的,不要在外面再包一层引号:

Terminal window
# 正确写法
fd -e bam -x samtools sort {} -o sorted/{/}
# 复杂命令用 sh -c
fd -e bam -x sh -c 'samtools sort "$1" -o "sorted/$(basename "$1")"' _ {}
# _ 是 $0 的占位符,{} 传给 $1

坑7:bat 不支持大文件分页时内存溢出#

症状:bat 50GB.fastq 直接卡死。

bat 会把整个文件读入内存做语法高亮。大文件请用 head / tail 配合 bat:

Terminal window
# 只看前面部分
head -1000 huge.fastq | bat --paging=never -l fasta
# 或直接用 less(也有语法高亮但没 bat 漂亮)
less huge.fastq

坑8:jq 的数值精度丢失#

症状:jq 处理后的大整数(如基因组坐标)被转成了科学计数法。

Terminal window
# jq 默认把大数字转为浮点
echo '{"pos": 248956422}' | jq '.pos'
# 输出:248956422 ← 恰好还在安全范围
# 但更大的:9007199254740993 就会丢失精度
# 如果 JSON 中包含超大整数,用 --raw-output 或字符串处理

7. 小结#

你要做的事旧工具新工具提速
看文件内容catbat—(体验提升)
找文件findfd5-10×
搜内容greprg5-30×
处理 JSONPython/R 脚本jq10-50×(开发时间)

这四个工具加到 .bashrc 里设置好 alias,花 10 分钟习惯一下,之后每天能省半小时以上。搞生信的,时间是最大的成本。


本文于 2025-08-07 在 Debian 13 上实测完成。bat v0.24.0,fd v10.2.0,ripgrep v14.1.1,jq v1.7.1。

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

命令行效率工具:bat/fd/ripgrep/jq
https://fg.ink/posts/cli-efficiency-tools/
作者
风观
发布于
2026-01-15
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
风观
风有来路,观有所思
分类
标签
站点统计
文章
50
分类
1
标签
29
总字数
61,837
运行时长
0
最后活动
0 天前

文章目录