在Snakemake中,使用shell()函数执行多个命令的推荐方法是什么?
在规则的 run
块中(规则可以指定 run:
而不是 shell:
),您可以多次调用 shell()
:
rule processing_step:
input:
# [...]
output:
# [...]
run:
shell("somecommand {input} > tempfile")
shell("othercommand tempfile {output}")
否则,由于run块接受Python代码,您可以构建一组字符串命令,并对它们进行迭代:
rule processing_step:
input:
# [...]
output:
# [...]
run:
commands = [
"somecommand {input} > tempfile",
"othercommand tempfile {output}"
]
for c in commands:
shell(c)
如果执行规则时不需要使用Python代码,您可以在shell
块中使用三引号字符串,并像在shell脚本中一样编写命令。这可能是纯shell规则中最易读的方法:
rule processing_step:
input:
# [...]
output:
# [...]
shell:
"""
somecommand {input} > tempfile
othercommand tempfile {output}
"""
如果shell命令依赖于前一个命令的成功/失败,它们可以与常规的shell脚本运算符(如||
和&&
)一起使用:
rule processing_step:
input:
# [...]
output:
# [...]
shell:
"command_one && echo 'command_one worked' || echo 'command_one failed'"
我想提供一个例子。虽然它可能不是直接回答用户的问题,但当我搜索类似的内容并尝试弄清如何运行多个shell命令并在特定目录下运行其中一些命令时,我遇到了这个问题。
为了保持代码整洁,您可以使用shell脚本。
假设我有一个名为scripts/run_somecommand.sh
的shell脚本,它执行以下操作:
#!/usr/bin/env sh
input=$(realpath $1)
output=$(realpath $2)
log=$(realpath $3)
sample="$4"
mkdir -p data/analysis/${sample}
cd data/analysis/${sample}
somecommand --input ${input} --output ${output} 2> ${log}
然后在你的Snakemake规则中,你可以这样做
rule somerule:
input:
"data/{sample}.fastq"
output:
"data/analysis/{sample}/{sample}_somecommand.json"
log:
"logs/somecommand_{sample}.log"
shell:
"scripts/run_somecommand.sh {input} {output} {log} {sample}"
注意: 如果您正在使用 Mac 并且没有 realpath
命令,可以使用 brew install coreutils
进行安装,这是一个非常方便的命令。