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
- 它搜索 *.fasta 文件并处理每个“命中”行
- 它将grep的每个结果按空格拆分并获得第6个元素作为新名称
- 它将 grep 的每个结果拆分为 : 并将第一个元素作为旧名称
- 它
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
。
我有多个 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
- 它搜索 *.fasta 文件并处理每个“命中”行
- 它将grep的每个结果按空格拆分并获得第6个元素作为新名称
- 它将 grep 的每个结果拆分为 : 并将第一个元素作为旧名称
- 它 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
。