生信面试 Linux 命令速查¶
一句话概述:生信工程师面试必考 Linux 命令,掌握文件操作、文本处理三剑客(grep/sed/awk)、管道重定向、进程管理和 Shell 脚本,就能应对 90% 的面试题。
核心知识点速查表¶
| 概念 | 白话解释 |
|---|---|
| Shell | 命令行解释器,把你输入的命令翻译给操作系统 |
| Bash | 最常用的 Shell 类型(Born Again Shell) |
| 管道(|) | 把前一个命令的输出当作下一个命令的输入 |
| 重定向(>/<) | 把输出写到文件 或 把文件内容当输入 |
| 正则表达式 | 用特殊符号描述文本模式(如 ^ATG 表示以 ATG 开头) |
| 环境变量 | 系统级别的"全局变量"(如 PATH、HOME) |
| 权限 | 文件的读(r)/写(w)/执行(x)权限,分为 用户/组/其他 |
| 进程 | 正在运行的程序,可以前台/后台运行 |
一、文件与目录操作(高频考点)¶
# === 基础文件操作 ===
# 查看当前目录
pwd # Print Working Directory,打印当前路径
# 列出文件
ls # 列出当前目录文件
ls -l # 长格式(权限、大小、时间)
ls -lh # 人类可读大小(KB/MB/GB)
ls -la # 包含隐藏文件(以.开头的)
ls -lS # 按文件大小排序(大→小)
ls -lt # 按修改时间排序(新→旧)
# 切换目录
cd /home/user/data # 进入指定目录
cd .. # 返回上一级
cd ~ # 回到家目录
cd - # 回到上一次的目录
# 创建/删除
mkdir -p project/data/raw # -p 递归创建(父目录不存在也不报错)
rm file.txt # 删除文件
rm -r directory/ # 递归删除目录(危险!)
rm -rf directory/ # 强制递归删除(超危险!面试要说风险)
rmdir empty_dir/ # 只能删除空目录(安全)
# 复制/移动/重命名
cp file.txt backup.txt # 复制文件
cp -r dir1/ dir2/ # 递归复制目录
mv old_name.txt new_name.txt # 重命名
mv file.txt /target/dir/ # 移动文件
# 查看文件内容
cat file.txt # 显示全部内容(小文件用)
head -n 20 file.txt # 显示前20行
tail -n 20 file.txt # 显示后20行
tail -f logfile.log # 实时监控文件末尾(看日志用)
less file.txt # 分页查看(按q退出,/搜索)
wc -l file.txt # 统计行数
wc -w file.txt # 统计单词数
# 查找文件
find . -name "*.fastq.gz" # 在当前目录下找所有fastq.gz文件
find . -name "*.bam" -size +1G # 找大于1GB的BAM文件
find . -mtime -7 -name "*.log" # 找7天内修改过的log文件
which bwa # 查找命令的路径
locate samtools # 快速查找(需要updatedb)
# 文件信息
file sample.bam # 查看文件类型
stat file.txt # 详细文件信息(大小、时间、权限)
du -sh directory/ # 查看目录总大小
du -sh * | sort -rh | head # 找出当前目录最大的文件/目录
df -h # 查看磁盘使用情况
面试常问:软链接 vs 硬链接¶
# 软链接(符号链接)— 像快捷方式
ln -s /data/reference/hg38.fa ./hg38.fa # 创建软链接
# 特点:可以跨文件系统,删除源文件后链接失效
# 硬链接 — 像文件的另一个名字
ln /data/file.txt ./file_hardlink.txt # 创建硬链接
# 特点:不能跨文件系统,删除源文件后链接仍有效
# 生信中常用软链接,因为参考基因组等文件很大不想复制
二、文本处理三剑客(最高频考点)¶
grep — 文本搜索¶
# === grep: 在文件中搜索匹配的行 ===
grep "BRCA1" gene_list.txt # 搜索包含BRCA1的行
grep -i "brca1" gene_list.txt # -i 忽略大小写
grep -c ">" sequences.fasta # -c 统计匹配行数(fasta序列数)
grep -v "^#" file.vcf # -v 反选(去掉#开头的注释行)
grep -n "error" log.txt # -n 显示行号
grep -w "TP53" results.txt # -w 全词匹配(不会匹配到TP53BP1)
grep -r "pattern" directory/ # -r 递归搜索目录
grep -E "gene1|gene2|gene3" file.txt # -E 扩展正则(或)
grep -f gene_list.txt expression.tsv # -f 从文件读取多个模式
grep -A 1 ">" sequences.fasta # -A 1 显示匹配行及后1行(取fasta序列)
grep -B 2 "ERROR" log.txt # -B 2 显示匹配行及前2行
zgrep "PASS" variants.vcf.gz # zgrep 直接搜索压缩文件
# 面试经典:统计FASTA文件中的序列数
grep -c "^>" sequences.fasta # 统计以>开头的行数 = 序列数
sed — 流编辑器¶
# === sed: 按行处理文本(替换、删除、插入) ===
# 替换
sed 's/chr//' file.txt # 删除每行第一个chr(chr1→1)
sed 's/chr//g' file.txt # 删除所有chr(g=全局)
sed 's/\t/,/g' file.tsv > file.csv # tab转逗号(TSV→CSV)
sed -i 's/old/new/g' file.txt # -i 直接修改文件(危险,建议先备份)
sed -i.bak 's/old/new/g' file.txt # -i.bak 修改前自动备份
# 删除
sed '1d' file.txt # 删除第1行(去表头)
sed '/^#/d' file.vcf # 删除所有#开头的行(去注释)
sed '/^$/d' file.txt # 删除空行
sed '1,5d' file.txt # 删除第1到5行
# 打印
sed -n '10,20p' file.txt # 只打印第10-20行
sed -n '/START/,/END/p' file.txt # 打印START到END之间的内容
# 面试经典:提取FASTA文件中特定序列
sed -n '/^>gene_name/,/^>/p' all.fasta | sed '$d' # 提取指定序列
awk — 列处理神器¶
# === awk: 按列处理文本(最强大) ===
# awk '{动作}' 文件 — 对每行执行动作
# $0=整行, $1=第1列, $2=第2列, NR=行号, NF=列数
# 基础用法
awk '{print $1}' file.txt # 打印第1列
awk '{print $1, $3}' file.txt # 打印第1列和第3列
awk -F'\t' '{print $1, $2}' file.tsv # -F指定分隔符为tab
awk -F',' '{print $1}' file.csv # -F指定分隔符为逗号
# 条件过滤
awk '$3 > 100' file.txt # 第3列大于100的行
awk '$5 == "PASS"' file.vcf # 第5列等于PASS的行
awk '$3 > 1 && $6 < 0.05' results.tsv # 多条件:log2FC>1且pvalue<0.05
awk 'NR > 1' file.txt # 跳过第1行(去表头)
awk 'NR==1 || $3 > 100' file.txt # 保留表头+第3列>100的行
# 计算
awk '{sum += $2} END {print sum}' file.txt # 求第2列总和
awk '{sum += $2} END {print sum/NR}' file.txt # 求第2列平均值
awk '{if($2>max) max=$2} END {print max}' file.txt # 求第2列最大值
# 格式化输出
awk -F'\t' '{printf "%s\t%.2f\n", $1, $2}' file.tsv # 格式化输出(保留2位小数)
awk -F'\t' 'BEGIN{OFS="\t"} {print $1, $2*2}' file.tsv # 第2列乘以2
# 面试经典:统计VCF文件中每条染色体的变异数
awk '!/^#/ {count[$1]++} END {for(c in count) print c, count[c]}' file.vcf
# 面试经典:提取差异表达基因(|log2FC|>1 且 padj<0.05)
awk -F'\t' 'NR==1 || ($3>1 || $3<-1) && $7<0.05' deseq2_results.tsv
# 面试经典:计算FASTQ文件reads数
awk 'END {print NR/4}' sample.fastq # FASTQ每4行一条read
三、管道与重定向(核心概念)¶
# === 管道:把命令串起来 ===
# 基本管道
cat file.txt | head -20 # 查看前20行
cat file.txt | sort | uniq # 排序后去重
cat file.txt | sort | uniq -c | sort -rn # 统计每个值出现次数并排序
# 多命令管道(生信经典)
zcat sample.fastq.gz | head -4 # 查看压缩fastq的前4行
samtools view file.bam | wc -l # 统计BAM文件的比对reads数
bcftools view -H file.vcf | wc -l # 统计VCF中的变异数(去掉header)
# === 重定向 ===
command > output.txt # 标准输出写入文件(覆盖)
command >> output.txt # 标准输出追加到文件
command 2> error.log # 标准错误写入文件
command > output.txt 2>&1 # 标准输出和错误都写入文件
command > /dev/null 2>&1 # 丢弃所有输出(静默运行)
# === sort/uniq/cut/paste ===
sort -k2,2n file.txt # 按第2列数值排序
sort -k1,1 -k2,2n file.txt # 先按第1列字母排序,再按第2列数值排序
sort -t$'\t' -k3,3rn file.tsv # tab分隔,按第3列逆序数值排序
uniq -c sorted.txt # 统计连续重复行数(需先sort)
cut -f1,3 file.tsv # 提取第1和第3列(tab分隔)
cut -d',' -f2 file.csv # 提取逗号分隔的第2列
paste file1.txt file2.txt # 横向合并两个文件(按行拼接)
# 面试经典:找出两个基因列表的交集/差集
sort gene_list1.txt gene_list2.txt | uniq -d # 交集(出现2次)
sort gene_list1.txt gene_list2.txt | uniq -u # 差集(只出现1次)
comm -12 <(sort list1.txt) <(sort list2.txt) # 交集(更准确)
comm -23 <(sort list1.txt) <(sort list2.txt) # list1有list2没有
四、压缩与打包¶
# === 压缩/解压 ===
gzip file.fastq # 压缩(原文件消失,变成.gz)
gzip -k file.fastq # 压缩并保留原文件
gunzip file.fastq.gz # 解压
zcat file.fastq.gz | head # 不解压直接查看压缩文件
# tar 打包
tar -czf archive.tar.gz directory/ # 打包+gzip压缩
tar -xzf archive.tar.gz # 解压tar.gz
tar -xjf archive.tar.bz2 # 解压tar.bz2
tar -tzf archive.tar.gz # 查看压缩包内容(不解压)
# pigz — 多线程压缩(生信常用,大文件快很多)
pigz -p 8 file.fastq # 8线程压缩
unpigz file.fastq.gz # 多线程解压
五、权限与进程管理¶
# === 权限 ===
chmod 755 script.sh # rwxr-xr-x(用户可读写执行,其他人读和执行)
chmod +x script.sh # 给脚本添加执行权限
chmod -R 755 directory/ # 递归修改目录权限
chown user:group file.txt # 修改文件所有者
# 权限数字含义:r=4, w=2, x=1
# 755 = rwxr-xr-x = 用户(4+2+1) 组(4+0+1) 其他(4+0+1)
# 644 = rw-r--r-- = 用户(4+2+0) 组(4+0+0) 其他(4+0+0)
# === 进程管理 ===
command & # 后台运行命令
nohup command & # 后台运行且退出终端不中断
nohup bwa mem ref.fa R1.fq R2.fq > aligned.sam 2>bwa.log & # 生信常用写法
jobs # 查看后台任务
fg %1 # 把后台任务1调到前台
bg %1 # 把暂停的任务放到后台继续运行
Ctrl+C # 终止前台进程
Ctrl+Z # 暂停前台进程
ps aux # 查看所有进程
ps aux | grep bwa # 查找bwa相关进程
top # 实时查看系统资源(CPU/内存)
htop # 更好看的top(需安装)
kill PID # 终止进程
kill -9 PID # 强制终止进程
killall bwa # 终止所有bwa进程
# screen/tmux — 保持远程会话(面试加分项)
screen -S analysis # 创建名为analysis的会话
# Ctrl+A,D # 断开会话(后台继续运行)
screen -r analysis # 重新连接会话
screen -ls # 列出所有会话
tmux new -s mywork # 创建tmux会话
# Ctrl+B,D # 断开
tmux attach -t mywork # 重连
六、Shell 脚本基础¶
#!/bin/bash
# ========== 生信分析脚本模板 ==========
# 用途:批量处理FASTQ质控
# 作者:面试演示
# === 变量 ===
INPUT_DIR="/data/raw" # 输入目录
OUTPUT_DIR="/data/clean" # 输出目录
THREADS=8 # 线程数
# === 创建输出目录 ===
mkdir -p ${OUTPUT_DIR} # -p 存在不报错
# === 循环处理每个样本 ===
for fq1 in ${INPUT_DIR}/*_R1.fastq.gz; do # 遍历所有R1文件
# 获取样本名
sample=$(basename ${fq1} _R1.fastq.gz) # 从文件名提取样本名
fq2=${INPUT_DIR}/${sample}_R2.fastq.gz # 对应的R2文件
echo "Processing ${sample}..." # 打印进度
# 检查R2文件是否存在
if [ ! -f ${fq2} ]; then # -f 检查文件存在
echo "WARNING: ${fq2} not found, skipping"
continue # 跳过这个样本
fi
# 运行 fastp 质控
fastp \
-i ${fq1} \ # R1输入
-I ${fq2} \ # R2输入
-o ${OUTPUT_DIR}/${sample}_R1.clean.fq.gz \ # R1输出
-O ${OUTPUT_DIR}/${sample}_R2.clean.fq.gz \ # R2输出
-w ${THREADS} \ # 线程数
-j ${OUTPUT_DIR}/${sample}.json \ # JSON报告
-h ${OUTPUT_DIR}/${sample}.html # HTML报告
# 检查运行是否成功
if [ $? -eq 0 ]; then # $? 获取上一条命令的退出码
echo "${sample} done successfully"
else
echo "ERROR: ${sample} failed!"
fi
done
echo "All samples processed!"
# === 常用条件判断 ===
# [ -f file ] 文件存在
# [ -d dir ] 目录存在
# [ -s file ] 文件存在且不为空
# [ -z "$var" ] 变量为空
# [ "$a" == "$b" ] 字符串相等
# [ $a -gt $b ] 数值大于
# [ $a -lt $b ] 数值小于
七、生信特有的 Linux 操作¶
# === 生信文件格式快速查看 ===
# FASTQ
zcat sample_R1.fastq.gz | head -4 # 查看前1条read(4行一组)
zcat sample_R1.fastq.gz | awk 'NR%4==2' | head # 只看序列行
# FASTA
grep -c "^>" genome.fasta # 统计序列数
awk '/^>/ {name=$0; next} {print name, length($0)}' ref.fa # 每条序列长度
# SAM/BAM
samtools view -h file.bam | head -30 # 查看BAM的前30行(含header)
samtools view -c file.bam # 统计总reads数
samtools view -c -F 4 file.bam # 统计比对上的reads数
samtools view -c -f 4 file.bam # 统计没比对上的reads数
samtools flagstat file.bam # 比对统计摘要
samtools idxstats file.bam # 每条染色体的reads数
# VCF
bcftools stats file.vcf > vcf_stats.txt # VCF统计
grep -v "^#" file.vcf | wc -l # 变异数(去掉header)
grep -v "^#" file.vcf | awk '{print $1}' | sort | uniq -c # 每条染色体变异数
# BED
awk '{sum += $3-$2} END {print sum}' target.bed # BED文件覆盖区域总长度
sort -k1,1 -k2,2n file.bed # 按染色体和位置排序BED
bedtools merge -i sorted.bed # 合并重叠区间
八、常见报错与解决¶
| 问题 | 原因 | 解决方法 |
|---|---|---|
| Permission denied | 没有执行权限 | chmod +x script.sh |
| command not found | 软件没装或不在PATH中 | which cmd 检查,加入PATH或conda activate |
| No space left on device | 磁盘满了 | df -h 检查,du -sh * 找大文件 |
| Killed / OOM | 内存不足被系统杀死 | 减少并行数或申请更多内存 |
| \r: command not found | Windows换行符 | dos2unix script.sh 或 sed -i 's/\r$//' |
| Argument list too long | 通配符匹配文件太多 | 用 find ... -exec 或 xargs |
| Broken pipe | 管道前面的命令还没结束后面就关了 | 通常可忽略,或用 head 时正常 |
九、面试高频问题¶
Q1:如何查看一个 FASTQ 文件有多少条 reads?
方法1:
wc -l file.fastq | awk '{print $1/4}'(行数除以4) 方法2:awk 'END{print NR/4}' file.fastq压缩文件:zcat file.fastq.gz | awk 'END{print NR/4}'
Q2:如何在不解压的情况下查看 .gz 文件内容?
zcat file.gz | head(查看前几行)、zgrep "pattern" file.gz(搜索)、zless file.gz(分页查看)。
Q3:awk 和 sed 的区别?
awk 擅长按列处理(字段分割、计算、统计),sed 擅长按行处理(替换、删除、插入)。简单替换用 sed,需要列运算用 awk。
Q4:如何让程序在退出终端后继续运行?
(1)
nohup command &(最简单);(2)screen/tmux(推荐,可以重新连接查看输出);(3) 提交到作业调度系统(如 SLURM)。
Q5:解释一下 Linux 文件权限 755 的含义?
7=rwx(所有者可读写执行),5=r-x(组用户可读执行),5=r-x(其他用户可读执行)。数字计算:r=4, w=2, x=1。
十、速查表¶
# === 生信 Linux 命令速查 ===
# 文件查看
head -n 20 file | tail -n 10 # 查看第11-20行
wc -l file # 行数
du -sh * # 各文件/目录大小
# 文本处理
grep -c "^>" file.fa # FASTA序列数
grep -v "^#" file.vcf | wc -l # VCF变异数
awk -F'\t' '$7<0.05' results.tsv # 筛选p<0.05
sed 's/chr//' file.txt # 去除chr前缀
cut -f1,3 file.tsv # 提取第1和第3列
sort file | uniq -c | sort -rn # 频率统计
# 集合运算
comm -12 <(sort a.txt) <(sort b.txt) # 交集
comm -23 <(sort a.txt) <(sort b.txt) # a独有
# 后台运行
nohup cmd > out.log 2>&1 & # 后台运行+日志
# 批量处理
for f in *.fastq.gz; do echo $f; done # 遍历文件
find . -name "*.bam" -exec samtools index {} \; # 批量建索引
# 磁盘管理
df -h # 磁盘使用
du -sh * | sort -rh | head # 最大文件
参考资料:Linux Pocket Guide (O'Reilly 2024)、生信菜鸟团 Linux 教程、Biostars 面试经验帖