如何在Bash中重命名文件以增加名称中的数字?

6

我有几千个这样命名的文件:

Cyprinus_carpio_600_nanopore_trim_reads.fasta                
Cyprinus_carpio_700_nanopore_trim_reads.fasta               
Cyprinus_carpio_800_nanopore_trim_reads.fasta                
Cyprinus_carpio_900_nanopore_trim_reads.fasta 
Vibrio_cholerae_3900_nanopore_trim_reads.fasta

针对第一二个单词80种不同的变体(即80个不同的物种),我希望将这些文件都重命名,使得文件编号增加100 - 例如:

Vibrio_cholerae_3900_nanopore_trim_reads.fasta 

would become

Vibrio_cholerae_4000_nanopore_trim_reads.fasta

或者

Cyprinus_carpio_300_nanopore_trim_reads.fasta

would become

Cyprinus_carpio_400_nanopore_trim_reads.fasta

很不幸,我无法弄清如何重命名它们,我试图遵循https://unix.stackexchange.com/questions/40523/rename-files-by-incrementing-a-number-within-the-filename上的解决方案,有些成功。

但是我无法使其在文件名内部起作用,如果这有所帮助,我正在运行Ubuntu 18.04。


文件名中只有一个数字吗?还是可能有多个数字?它总是在第3部分,还是可能出现在其他地方? - Mark Setchell
嗨,它总是在相同的位置,并且文件名中只有一个数字,谢谢。 - MolEcologist29
4个回答

11
如果你可以获取Perl版本的rename,那么使用起来就像这样简单:
rename -n 's/(\d+)/$1 + 100/e' *fasta

样例输出

'Ciprianus_maximus_11_fred.fasta' would be renamed to 'Ciprianus_maximus_111_fred.fasta'
'Ciprianus_maximus_300_fred.fasta' would be renamed to 'Ciprianus_maximus_400_fred.fasta'
'Ciprianus_maximus_3900_fred.fasta' would be renamed to 'Ciprianus_maximus_4000_fred.fasta'

如果你不会读Perl,那么这段话的意思是:"进行一次单个替换。无论何时看到一排连续的数字(\d+),记住它们(因为我把它放在括号里),然后用该数字串的计算结果($1)加上100来替换它们." 如果测试运行正确,请移除 -n。唯一的"棘手的部分"是在替换末尾使用了 e ,这意味着在替换式中评估表达式,或者说进行了"计算替换"

这看起来不错,我遇到的唯一问题是因为它是增量步骤,我遇到了以下问题:Zygosaccharomyces_rouxii_3000_nanopore_trim_reads.fasta未重命名:Zygosaccharomyces_rouxii_3100_nanopore_trim_reads.fasta已存在。 - MolEcologist29
请注意,有两个常见的可执行文件名为“rename”。如果您使用的是“util-linux”软件包提供的那个,您将没有“-n”选项。 - David C. Rankin
@DavidC.Rankin 是的,谢谢。这就是为什么我说“Perl风味”的原因!如果您知道正确的软件包,也许您可以添加它吗?再次感谢。 - Mark Setchell
不确定你的所有文件实际上是如何命名的。也许你可以对每个文件名加上105,然后再减去5,这样它们就不会冲突了?请在文件的备份副本上进行操作。 - Mark Setchell
1
@MarkSetchell,不幸的是这取决于发行版,例如Archlinux提供了一个perl-rename包,Debian将其提供为rename包,但openSuSE将其捆绑在一些不容易看出来的外来perl包中。最好的建议是首先运行rename -h :) - David C. Rankin
2
如果您想在数字旁边添加文本,可以使用s/(\d+)/"blabla".($1+100)/e - NaN

1
如果您的字符串中只有一个数字,那么以下两行代码应该可以帮助您解决问题。
filename="Vibrio_cholerae_3900_nanopore_trim_reads.fasta"
var=$(echo $filename | grep -oP '\d+')
echo ${filename/${var}/$((var+100))}

不要回显更改后的文件名,你可以将其存入变量中,然后使用mv命令进行重命名。


最好使用 "+" 而不是 "" 进行 "grep",因为有些版本不使用 "". - l'L'l
1
@我会更新我的答案。 - Ashishkumar Singh

1

考虑到文件名冲突是按递增顺序排列的,我最初想到的是颠倒顺序,但在字母(标准)排序中仍可能存在冲突,因为与数字排序不同。
那么,如何采取两步解决方案:第一步,在文件名中插入转义字符(或任何不出现在文件名中的字符),第二步将其删除。

#!/bin/bash

esc=$'\033' # ESC character

# 1st pass: increase the number by 100 and insert a ESC before it
for f in *.fasta; do
    num=${f//[^0-9]/}
    num2=$((num + 100))
    f2=${f/$num/$esc$num2}
    mv "$f" "$f2"
done

# 2nd pass: remove the ESC from the filename
for f in *.fasta; do
    f2=${f/$esc/}
    mv "$f" "$f2"
done

0

Mark的perl-rename解决方案看起来很不错,但你应该使用它两次,并增加50以避免名称冲突。如果你找不到这种重命名方式,可以尝试我的rene.py(https://rene-file-renamer.sourceforge.io),命令为(也要应用两次)rene *_*_*_* *_*_?_* B/50。rene会更容易一些,因为它会自动显示更改并询问您是否要进行更改,如果您改变主意,它还有撤消功能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接