我一直在运行roary
pangenome 管道,我需要在 for 循环中编写一个脚本,例如我有一个gff
文件如下,
a.gff
b.gff
5.gff
101.gff
clustered_proteins
我需要运行一个命令来从roary
管道中检索独特的基因,如下所示,
query_pan_genome -a difference --input_set_one a.gff --input_set_two b.gff,5.gff,101.gff -g clustered_proteins
query_pan_genome -a difference --input_set_one b.gff --input_set_two a.gff,5.gff,101.gff -g clustered_proteins
query_pan_genome -a difference --input_set_one 5.gff --input_set_two a.gff,b.gff,101.gff -g clustered_proteins
query_pan_genome -a difference --input_set_one 101.gff --input_set_two a.gff,b.gff,5.gff -g clustered_proteins
为了做同样的事情,我编写了一个脚本,如下所示,
file1=*.gff
file2=*.gff
file3="-f "$file1-$file2"
for file in *.gff
do
query_pan_genome -a difference --input_set_one "$file1" --input_set_two "$file3" -g clustered_proteins
done
但是上面的脚本没有达到我的目的,我只知道脚本很简单,这对我来说很难写。请帮助我完善剧本。
提前致谢。
答案1
使用/bin/sh
:
#!/bin/sh
set -- *.gff
for name do
shift
( IFS=,
query_pan_genome -a difference \
--input_set_one "$name" \
--input_set_two "$*" \
-g clustered_proteins
)
set -- "$@" "$name"
done
这首先将位置参数设置为与模式匹配的文件名列表*.gff
。然后循环遍历该列表,将变量设置name
为当前文件名的值。
在循环中,对于每个文件名,第一个位置参数将从位置参数列表中移出。这个移出的元素对应于也在 中找到的当前文件名$name
。在 后shift
,位置参数列表包含其他文件名,但不包含$name
.
在(...)
循环的子shell中,我们本地设置IFS
为逗号。这意味着它将"$*"
扩展为由当前位置参数列表组成的字符串,并以逗号作为分隔符。
然后,我们query_pan_genome
使用$name
文件名和其他文件名作为逗号分隔列表来调用该实用程序。
在 subshell 之后,就在循环体结束之前,当前名称被放回到位置参数列表中,但在最后。
即使我们迭代该列表,修改循环内的位置参数列表也没有问题。我们迭代的列表是我们在循环中使用shift
and修改的列表的不变副本set
(for
循环始终迭代静态元素列表)。
鉴于问题中的 GFF 文件列表,上面的代码最终将执行以下四个命令:
query_pan_genome -a difference --input_set_one 101.gff --input_set_two 5.gff,a.gff,b.gff -g clustered_proteins
query_pan_genome -a difference --input_set_one 5.gff --input_set_two a.gff,b.gff,101.gff -g clustered_proteins
query_pan_genome -a difference --input_set_one a.gff --input_set_two b.gff,101.gff,5.gff -g clustered_proteins
query_pan_genome -a difference --input_set_one b.gff --input_set_two 101.gff,5.gff,a.gff -g clustered_proteins
答案2
使用以下方法更容易zsh
:
#! /bin/zsh -
files=(*.gff(N))
# don't run that command if there are fewer than 2 files
(( $#files < 2 )) ||
for f ($files)
query_pan_genome -a difference \
--input_set_one $f \
--input_set_two ${(j[,])files:#$f} \
-g clustered_proteins
在哪里
${array:#pattern}
扩展到数组中与模式不匹配的元素,因此这里使用except${files#$f}
的元素。$files
$f
${(j[,])array}
将数组的元素与 相连,
。
而不是*.gff(N)
,您可能希望使用*.gff(Nn)
globn
限定符打开numericglobsort
该 glob 扩展选项的位置,这样就file10.gff
可以了后 file2.gff
例如。
答案3
您可以使用数组,循环其索引并暂时取消设置每个索引:
#! /bin/bash
input_files=(*.gff)
IFS=,
for index in "${!input_files[@]}"
do
input_file=${input_files[$index]}
unset input_files[$index]
echo "$input_file" "${input_files[*]}"
input_files[$index]=$input_file
done
输出示例:
101.gff 5.gff,a.gff,b.gff
5.gff 101.gff,a.gff,b.gff
a.gff 101.gff,5.gff,b.gff
b.gff 101.gff,5.gff,a.gff