chen7qi的个人博客分享 http://blog.sciencenet.cn/u/chen7qi

博文

有了这些,文件批量重命名还需要求助其它工具吗?

已有 1672 次阅读 2020-3-30 21:22 |系统分类:科研笔记

经验整理

NGS系列文章包括NGS基础、转录组分析 (Nature重磅综述|关于RNA-seq你想知道的全在这)、ChIP-seq分析 (ChIP-seq基本分析流程)、单细胞测序分析 (重磅综述:三万字长文读懂单细胞RNA测序分析的最佳实践教程 (原理、代码和评述))、DNA甲基化分析、重测序分析、GEO数据挖掘(典型医学设计实验GEO数据分析 (step-by-step) - Limma差异分析、火山图、功能富集)等内容。

简单重命名

Linux下文件重命名可以通过两个命令完成(收藏| 15 个你非了解不可的 Linux 特殊字符,妈妈再也不用担心我看不懂这些符号了!),mvrename

  • mv: 直接运行可以进行单个文件的重命名,如 mv old_name.txt new_name.txt

  • rename: 默认支持单个文件或有固定规律的一组文件的批量重命名,示例如下。

rename演示

使用touch新建文件(Linux - 文件操作),两个样品(分别是易生信a,易生信b),各自双端测序得到的FASTQ文件(Linux - 文件排序和FASTA文件操作)。

ysx@ehbio:~/test$ touch YSX_a_1.fq.gz YSX_a_2.fq.gz YSX_b_2.fq.gz YSX_b_1.fq.gz
ysx@ehbio:~/test$ ls
YSX_a_1.fq.gz  YSX_a_2.fq.gz  YSX_b_1.fq.gz  YSX_b_2.fq.gz

把文件名中的易生信(YSX)改为易汉博 (ehbio):

# rename '被替换文字' '要替换成的文字' 操作对象
ysx@ehbio:~/test$ rename 'YSX' 'ehbio' *.gz
ysx@ehbio:~/test$ ls
ehbio_a_1.fq.gz  ehbio_a_2.fq.gz  ehbio_b_1.fq.gz  ehbio_b_2.fq.gz

不同操作系统,rename的使用方法略有不同。印象中:

# 在CentOS下,该命令未起作用
ysx@ehbio:~/test$ rename 's/ehbio_//' *
ysx@ehbio:~/test$ ls
ehbio_a_1.fq.gz  ehbio_a_2.fq.gz  ehbio_b_1.fq.gz  ehbio_b_2.fq.gz

# 如果写的rename命令没发挥作用,使用man rename查看其具体使用方法, 个人经验,无外乎上面提到的两种用法。
ysx@ehbio:~/test$ man rename

# NAME
#        rename - rename files
#
# SYNOPSIS
#        rename [options] expression replacement file...

替换后缀:

# 替换后缀
ysx@ehbio:~/test$ rename 'fq' 'fastq' *.gz
ysx@ehbio:~/test$ ls
ehbio_a_1.fastq.gz  ehbio_a_2.fastq.gz  ehbio_b_1.fastq.gz  ehbio_b_2.fastq.gz

复杂重命名

但有时,需要重命名的文件不像上面那样有很清晰的模式,直接可以替换,需要多几步处理获得对应关系。

假如已经有对应关系

如下name.map.txt是自己手动编写的文件(Linux - 文件内容操作),a对应Controlb对应Treatment

ysx@ehbio:~/test$ ls
name.map.txt ehbio_a_1.fastq.gz  ehbio_a_2.fastq.gz  ehbio_b_1.fastq.gz  ehbio_b_2.fastq.gz

ysx@ehbio:~/test$ cat name.map.txt
a    Control
b    Treatment

组合文件名,使用mv重命名

首先组合出原名字和最终名字(Linux - 常用和不太常用的实用awk命令):

ysx@ehbio:~/test$ awk '{print "ehbio_"$1"_1.fastq.gz", "ehbio_"$2"_1.fastq.gz", "ehbio_"$1"_2.fastq.gz",  "ehbio_"$2"_2.fastq.gz"}' name.map.txt
ehbio_a_1.fastq.gz ehbio_Control_1.fastq.gz ehbio_a_2.fastq.gz ehbio_Control_2.fastq.gz
ehbio_b_1.fastq.gz ehbio_Treatment_1.fastq.gz ehbio_b_2.fastq.gz ehbio_Treatment_2.fastq.gz

加上mv

ysx@ehbio:~/test$ awk '{print "mv ehbio_"$1"_1.fastq.gz ehbio_"$2"_1.fastq.gz"; print "mv ehbio_"$1"_2.fastq.gz ehbio_"$2"_2.fastq.gz";}' name.map.txt
mv ehbio_a_1.fastq.gz ehbio_Control_1.fastq.gz
mv ehbio_a_2.fastq.gz ehbio_Control_2.fastq.gz
mv ehbio_b_1.fastq.gz ehbio_Treatment_1.fastq.gz
mv ehbio_b_2.fastq.gz ehbio_Treatment_2.fastq.gz

可以直接拷贝上面的输出再粘贴运行,或存储为文件运行:

ysx@ehbio:~/test$ awk '{print "mv ehbio_"$1"_1.fastq.gz ehbio_"$2"_1.fastq.gz"; print "mv ehbio_"$1"_2.fastq.gz ehbio_"$2"_2.fastq.gz";}' name.map.txt >rename.sh
ysx@ehbio:~/test$ #bash rename.sh

也可以把print改为system直接运行:

ysx@ehbio:~/test$ ls
ehbio_a_1.fastq.gz  ehbio_a_2.fastq.gz  ehbio_b_1.fastq.gz  ehbio_b_2.fastq.gz  name.map.txt  rename.sh
ysx@ehbio:~/test$ awk '{system("mv ehbio_"$1"_1.fastq.gz ehbio_"$2"_1.fastq.gz"); system("mv ehbio_"$1"_2.fastq.gz ehbio_"$2"_2.fastq.gz");}' name.map.txt
ysx@ehbio:~/test$ ls
ehbio_Control_1.fastq.gz  ehbio_Control_2.fastq.gz  ehbio_Treatment_1.fastq.gz  ehbio_Treatment_2.fastq.gz  name.map.txt  rename.sh

使用rename会不会稍微简单一点?

一定注意符号匹配和避免误匹配(Linux - 常见错误和快捷操作)。

# 注意引号和空格
ysx@ehbio:~/test$ awk '{print("rename "$1" "$2" *.fastq.gz"); }' name.map.txt
rename a Control *.fastq.gz
rename b Treatment *.fastq.gz

# 上面的命令有什么问题吗?
# fastq中也存在a,是否也会被替换
# ehbio中也存在b,是否也会倍替换

ysx@ehbio:~/test$ awk '{system("rename "$1" "$2" *.fastq.gz"); }' name.map.txt

# 执行后,文件名都乱套了
ysx@ehbio:~/test$ ls
ehbio_b_1.fControlstq.gz  ehbio_b_2.fControlstq.gz  ehTreatmentio_Control_1.fastq.gz  ehTreatmentio_Control_2.fastq.gz  name.map.txt  rename.sh

# 再重命名回去,再次尝试
ysx@ehbio:~/test$ rename 'Control' 'a' *
ysx@ehbio:~/test$ rename 'Treatment' 'b' *
ysx@ehbio:~/test$ ls
ehbio_a_1.fastq.gz  ehbio_a_2.fastq.gz  ehbio_b_1.fastq.gz  ehbio_b_2.fastq.gz  name.map.txt  rename.sh

# 重命名两侧加下划线, 这也是我们做匹配时常需要注意的,尽量限制让匹配更准确
ysx@ehbio:~/test$ awk '{system("rename _"$1"_ _"$2"_ *.fastq.gz"); }' name.map.txt

# 打印出来看下
ysx@ehbio:~/test$ awk '{print("rename _"$1"_ _"$2"_ *.fastq.gz"); }' name.map.txt
# rename _a_ _Control_ *.fastq.gz
# rename _b_ _Treatment_ *.fastq.gz

# 这次没问题了
ysx@ehbio:~/test$ ls
ehbio_Control_1.fastq.gz  ehbio_Control_2.fastq.gz  ehbio_Treatment_1.fastq.gz  ehbio_Treatment_2.fastq.gz  name.map.txt  rename.sh

从原文件名获取对应关系

基于paste

像上面自己写好对应文件是一个方法,有时也可以从文件名推测规律,生成对应文件。

如下有一堆测序原始数据(NGS基础 - 高通量测序原理),选择A组样品来查看:

# 如下有一堆测序原始数据,选择A组样品来查看
ysx@ehbio:~/test2# ls A*

A1_FRAS192317015-1a_1.fq.gz  A2_FRAS192320421-1a_1.fq.gz  A3_FRAS192317017-1a_1.fq.gz
A1_FRAS192317015-1a_2.fq.gz  A2_FRAS192320421-1a_2.fq.gz  A3_FRAS192317017-1a_2.fq.gz

中间的那一串字符FRA...-是我们不需要的。

观察规律,先按下划线将文件名分割(_),再获取第1,3个元素;另外习惯性给生物重复前面也加上下划线(用到了sed的记忆匹配)(Linux - SED操作,awk的姊妹篇)。

ysx@ehbio:~/test2# ls A*.gz | cut -f 1,3 -d '_' | sed 's/\([A-E]\)/\1_/'
A_1_1.fq.gz
A_1_2.fq.gz
A_2_1.fq.gz
A_2_2.fq.gz

把原样品名字与新样品名字对应起来,这里用到了paste和输入重定向 (<)(Linux - 管道、标准输入输出):

ysx@ehbio:~/test2# paste <(ls A*.gz) <(ls A*.gz | cut -f 1,3 -d '_' | sed 's/\([A-E]\)/\1_/')
A1_FRAS192317015-1a_1.fq.gz    A_1_1_fq.gz
A1_FRAS192317015-1a_2.fq.gz    A_1_2_fq.gz
A2_FRAS192320421-1a_1.fq.gz    A_2_1_fq.gz
A2_FRAS192320421-1a_2.fq.gz    A_2_2_fq.gz
A3_FRAS192317017-1a_1.fq.gz    A_3_1_fq.gz
A3_FRAS192317017-1a_2.fq.gz    A_3_2_fq.gz

使用mv直接重命名 (还可以把这个脚本保存下来,保留原始名字和新名字的对应关系,万一操作错了,在看到结果异常时也可以方便回溯)(Bash概论 - Linux系列教程补充篇):

ysx@ehbio:~/test2# paste <(ls A*.gz) <(ls A*.gz | cut -f 1,3 -d '_' | sed 's/\([A-E]\)/\1_/') | sed 's#^#/bin/mv #'
/bin/mv A1_FRAS192317015-1a_1.fq.gz    A_1_1_fq.gz
/bin/mv A1_FRAS192317015-1a_2.fq.gz    A_1_2_fq.gz
/bin/mv A2_FRAS192320421-1a_1.fq.gz    A_2_1_fq.gz
/bin/mv A2_FRAS192320421-1a_2.fq.gz    A_2_2_fq.gz
/bin/mv A3_FRAS192317017-1a_1.fq.gz    A_3_1_fq.gz
/bin/mv A3_FRAS192317017-1a_2.fq.gz    A_3_2_fq.gz

软链接也是常用的 (但一定注意源文件使用全路径)(Linux - 原来你是这样的软连接):

ysx@ehbio:~/test2# paste <(ls *.gz) <(ls *.gz | sed 's/\./_/' | cut -f 1,3,4 -d '_' | sed 's/\([A-E]\)/analysis\/\1_/') | sed 's#^#ln -s `pwd`/#'
ln -s `pwd`/A1_FRAS192317015-1a_1.fq.gz    analysis/A_1_1_fq.gz
ln -s `pwd`/A1_FRAS192317015-1a_2.fq.gz    analysis/A_1_2_fq.gz
ln -s `pwd`/A2_FRAS192320421-1a_1.fq.gz    analysis/A_2_1_fq.gz
.
.
.
ln -s `pwd`/E15_FRAS192317028-1a_1.fq.gz    analysis/E_15_1_fq.gz
ln -s `pwd`/E15_FRAS192317028-1a_2.fq.gz    analysis/E_15_2_fq.gz

基于awk

转换下输入数据的格式,字符处理在awk也可以操作(Linux - 常用和不太常用的实用awk命令),但我更习惯使用命令组合,每一步都用最简单的操作,不容易出错。

ysx@ehbio:~/test2# ls A*.gz | sed -e 's/\([A-E]\)/\1_/'
A_1_FRAS192317015-1a_1.fq.gz
A_1_FRAS192317015-1a_2.fq.gz
A_2_FRAS192320421-1a_1.fq.gz
A_2_FRAS192320421-1a_2.fq.gz
A_3_FRAS192317017-1a_1.fq.gz
A_3_FRAS192317017-1a_2.fq.gz
ysx@ehbio:~/test2# ls A*.gz | sed -e 's/\([A-E]\)/\1_/' -e 's/\./_./'
A_1_FRAS192317015-1a_1_.fq.gz
A_1_FRAS192317015-1a_2_.fq.gz
A_2_FRAS192320421-1a_1_.fq.gz
A_2_FRAS192320421-1a_2_.fq.gz
A_3_FRAS192317017-1a_1_.fq.gz
A_3_FRAS192317017-1a_2_.fq.gz

采用awk生成对应关系:

# 生成样品重复,计数出错了,每行记了一个数,而实际两行是一个样本。
ysx@ehbio:~/test2# ls A*.gz | sed -e 's/\([A-E]\)/\1_/' -e 's/\./_./' | awk 'BEGIN{OFS=" ";FS="_"}{sum[$1]+=1; print $0, $1"_"sum[$1]"_"$4$5;}'
A_1_FRAS192317015-1a_1_.fq.gz A_1_1.fq.gz
A_1_FRAS192317015-1a_2_.fq.gz A_2_2.fq.gz
A_2_FRAS192320421-1a_1_.fq.gz A_3_1.fq.gz
A_2_FRAS192320421-1a_2_.fq.gz A_4_2.fq.gz
A_3_FRAS192317017-1a_1_.fq.gz A_5_1.fq.gz
A_3_FRAS192317017-1a_2_.fq.gz A_6_2.fq.gz
# 稍微改进下
ysx@ehbio:~/test2# ls A*.gz | sed -e 's/\([A-E]\)/\1_/' -e 's/\./_./' | awk 'BEGIN{OFS=" ";FS="_"}{sum[$1]+=1; print $0, $1"_"sum[$1]"_"$4$5;}'
A_1_FRAS192317015-1a_1.fq.gz A_1_1.fq.gz
A_1_FRAS192317015-1a_2.fq.gz A_2_2.fq.gz
A_2_FRAS192320421-1a_1.fq.gz A_3_1.fq.gz
A_2_FRAS192320421-1a_2.fq.gz A_4_2.fq.gz
A_3_FRAS192317017-1a_1.fq.gz A_5_1.fq.gz
A_3_FRAS192317017-1a_2.fq.gz A_6_2.fq.gz

# 记得源文件名字的替换
ysx@ehbio:~/test2# ls A*.gz | sed -e 's/\([A-E]\)/\1_/' -e 's/\./_./' | awk 'BEGIN{OFS=" ";FS="_"}{sum[$1]+=1; print $0, $1"_"sum[$1]"_"$4$5;}' | sed -e 's/_//' -e 's/_\././' -e 's#^#ln -s `pwd`/#' |head
ln -s `pwd`/A1_FRAS192317015-1a_1.fq.gz A_1_1.fq.gz
ln -s `pwd`/A1_FRAS192317015-1a_2.fq.gz A_2_2.fq.gz

好了,重命名就到这了。有了这个思路,关键是如何根据自己的文件名字特征,构造对应的匹配关系

另外,Window下使用Git for windows应该也可以实现对应的操作(Windows轻松实现linux shell环境:gitforwindows)。




https://wap.sciencenet.cn/blog-118204-1226039.html

上一篇:只需一行代码,完美呈现Markdown格式,写作展示两不误
下一篇:Bioconda软件安装神器:多版本并存、环境复制、环境导出
收藏 IP: 114.250.123.*| 热度|

0

该博文允许注册用户评论 请点击登录 评论 (0 个评论)

数据加载中...
扫一扫,分享此博文

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2024-4-28 16:23

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部