重命名与 txt 文件中的字符串匹配的文件

rename files that match strings in a txt file

我正在尝试根据对 .txt 文件的匹配重命名多个文件 我的文件是

GCF_000698265.1_ASM69826v1_genomic.gff.gz
GCF_000785125.1_ASM78512v1_genomic.gff.gz
GCF_000934565.1_ASM93456v1_genomic.gff.gz
GCF_000963495.1_ASM96349v1_genomic.gff.gz

然后我的制表符分隔的 txt 文件如下所示:

GCF_000698265.1_ASM69826v1  Pseudomonas_str1
GCF_000785125.1_ASM78512v1  Pseudomonas_str2
GCF_000934565.1_ASM93456v1  Pseudomonas_str3
GCF_000963495.1_ASM96349v1  Pseudomonas_str4

因此,对于与文件第一列匹配的文件名,我想将文件重命名为第二列。 我试图了解如何通过管道传输 mv 和 awk,但我迷路了。 我希望我想要的输出如下所示:

Pseudomonas_str1_genomic.gff.gz
Pseudomonas_str2_genomic.gff.gz
Pseudomonas_str3_genomic.gff.gz
Pseudomonas_str4_genomic.gff.gz

有人可以帮忙吗? 我希望我已经清楚了,非常感谢!

使用 sedbash,假设 txt 文件名为 'rename.txt'

sed 's/^/mv /' rename.txt | bash

使用 awk:

awk '{system("mv "  " " )}' rename.txt

这里的关键是在每一行的开头插入“mv”并执行。

最后一个解决方案不使用任何外部工具,只是 bash:

while read old new; do mv "$old" "$new"; done < rename.txt

更新

根据 Alberto 的更新问题,进行了以下更改:

使用 sed:

sed sed 's/^/mv /;s/$/_genomic.gff.gz/' rename.txt | bash

注意:;s/$/_genomic.gff.gz/ 表达式表示:搜索行尾并在其后附加“_genomic.gff.gz”。这仅在每行中没有尾随空格时才有效。

使用 awk:

awk '{system("mv "  " "  "_genomic.gff.gz")}' rename.txt

使用Bash:

while read old new; do mv "$old" "${new}_genomic.gff.gz"; done < rename.txt

was trying to understand how to do it piping mv and awk

您可以使用 AWK 准备一系列命令,然后将其用作 bash 的标准输入。请注意,您的情况

file1.txt   cat.txt  
file2.txt   dog.txt
file3.txt   fish.txt
file4.txt   mouse.txt

是特定的,因为文件名中没有 spaces,如果名称中禁止使用 spaces 那么您可以简单地在行前添加 mv 例如,如果所述文件被命名renaming.txt 那么你可能会这样做

awk '{print "mv " [=11=]}' renaming.txt | bash

然而,如果任何名称中有 space,这将失败。如果允许使用 space,那么我建议使用 python(如果您使用 linux 机器,则可能已安装)按照以下方式,创建具有以下内容的文件 renamer.py

import os
with open("renaming.txt","r") as f:
    for line in f:
        src, dst = line.rstrip().split("\t")
        os.rename(src, dst)

其中 renaming.txt 是包含 2 tab-sheared 列的文件名,其中包含当前名称和所需名称,然后按如下方式使用它

python renamer.py

工作原理:opens renaming.txt 用于读取 (r) 的每一行,它会丢弃尾随的白色 spaces(换行符)和拆分行TAB 字符,第一部分转到 src,第二部分转到 dst,然后在 os.rename 函数中使用。

您可能 select 其他语言,最好是具有管理文件功能的语言,因为这将使为此任务开发代码更加容易。

所以我创建了一个有点大的合成 test-set,并且有意只让其中的 1 / 7th 匹配,然后 在任何地方都没有重复,因为合成文件名是 全部基于一个唯一的素数列表,文件也是随机排列的。

  • 254923 19113991 19113991 test_rename_output_2b.txt
  • 254923 15545069 15545069 test_need_to_rename_2.txt
 1784459  53025088 53025088 test_ref_lookup_2.txt
 2294305  87684148 87684148 total 

# gawk profile, created Thu May 12 03:57:36 2022

    # Rule(s)

     1  FNR == NR { # 1
1784459     do {
1784459         __[$!_]
1784459         getline
        } while (FNR == NR)
    }

     1  FNR != NR { # 1
254923      do {
254923          if ($!_ in __) { 
                    printf("gmv -vn %s "\
                                    "%s ;\n",$!!NF,$NF)
            }
        } while (getline)
    }

此解决方案的优点是它已经 pre-formatted 可以使用 mv 命令直接重命名(示例输出):

gmv -vn 'file522111333101.txt' 'newname_799042B2ED_.txt' ;
gmv -vn 'file2011113799793759.txt' 'newname_72518EBA3BC5F_.txt' ;
gmv -vn 'file476743673269.txt' 'newname_6F002325B5_.txt' ;
gmv -vn 'file7979798079897989.txt' 'newname_1C599585EE8185_.txt' ;
gmv -vn 'file211031042203.txt' 'newname_31226E289B_.txt' ;
gmv -vn 'file172888842428207.txt' 'newname_9D3DD209DF2F_.txt' ;

为了安全起见,我在所有重命名命令中都 pre-pended don't overwrite aka no-clobber aka -n 标志,可以直接发送到某个东西轻量级 dash 无需进一步的文件名操作即可执行。

性能我想是可以接受的-

  • mawk2 用了 1.218 secs 完成所有步骤(包括将最终输出文件写入磁盘)。