bash中的多个文件中将文件名替换为第一行的字符串

Replace filename to a string of the first line in multiple files in bash

我有多个 fasta 文件,其中第一行总是包含一个 > 和多个单词,例如:

File_1.fasta: 
>KY620313.1 Hepatitis C virus isolate sP171215 polyprotein gene, complete cds
File_2.fasta: 
>KY620314.1 Hepatitis C virus isolate sP131957 polyprotein gene, complete cds
File_3.fasta: 
>KY620315.1 Hepatitis C virus isolate sP127952 polyprotein gene, complete cds

我想从每个文件中取出以 sP* 开头的单词,并将每个文件重命名为这个字符串(例如:File_1.fasta 到 sP171215.fasta)。 到目前为止我有这个:

    $ for match in "$(grep -ro '>')";do
          fname=$("echo $match|awk '{print }'")
          echo mv "$match" "$fname"
      done

但是它不起作用,我总是得到错误:

grep: warning: recursive search of stdin

希望你能帮帮我!

这段代码有几件事情要做。 首先,.. 我实际上没有得到这个特定的错误,这可能是由于不同的版本。 由于 bash 扩展做得不好,它可能会解决 grep 将 '>' 解释为与 > 相同的事实。我建议也许去 "\>".

其次:

fname=$("echo $match|awk '{print }'") 里面的引号起到了意想不到的作用。你的代码应该像这样,如果有的话: fname="$(echo $match|awk '{print }')"

最后,要正确检索您的数据,这应该是您的最终代码:

for match in "$(grep -Hr "\>")"; do
  fname="$(echo "$match" | cut -d: -f1)"
  new_fname="$(echo "$match" | grep -o "sP[^ ]*")".fasta
  echo mv "$fname" "$new_fname"
done

说明: grep -H -> 你希望你的 grep 明确使用“包含文件名”,以防万一其他 shell 环境决定将 grep 别名为 grep -h (no filenames)

您不想在文件搜索中执行 grep -o,因为您希望在一个数据条目中同时包含文件名和“新文件名”。

尽管如此,我不明白您为什么要搜索“>”而不是 'sP' 的目录:

for match in "$(grep -Hro "sP[0-9]*")"

这不是完全相同的行为,并且有不同的边缘情况,但它可能适合您。

你可以使用这样的东西:

grep '>' *.fasta | while read -r line ; do
  new_name="$(echo $line | cut -d' ' -f 6)"
  old_name="$(echo $line | cut -d':' -f 1)"
  mv $old_name "$new_name.fasta"
done
  1. 它搜索 *.fasta 文件并处理每个“命中”行
  2. 它将grep的每个结果按空格拆分并获得第6个元素作为新名称
  3. 它将 grep 的每个结果拆分为 : 并将第一个元素作为旧名称
  4. 它 moves/renames 从旧文件名到新文件名

在 (g)awk 中非常简单:

创建文件“script.awk”:

FNR == 1 {
    for (i=1; i<=NF; i++) {
        if (index($i, "sP")==1) {
            print "mv", FILENAME, $i ".fasta"
            nextfile
        }
    }
}

使用它:

awk -f script.awk *.fasta > cmmd.txt

检查输出内容。

mv File_1.fasta sP171215.fasta
mv File_2.fasta sP131957.fasta

如果可以,使用 . cmmd.txt

启动重命名

对于目录中的所有 fasta 文件,在它们的第一行中搜索以 sP 开头的第一个单词,并使用该单词作为基本名称重命名它们。

使用 bash 数组:

for f in *.fasta; do
    arr=( $(head -1 "$f") )
    for word in "${arr[@]}"; do
        [[ "$word" =~ ^sP* ]] && echo mv "$f" "${word}.fasta" && break
    done
done

或使用 grep:

for f in *.fasta; do
    word=$(head -1 "$f" | grep -o "\bsP\w*")
    [ -z "$word" ] || echo mv "$f" "${word}.fasta"
done

注意:在测试正常后删除 echo