使用shell()执行多个shell命令的推荐方法是什么?

22

在Snakemake中,使用shell()函数执行多个命令的推荐方法是什么?

2个回答

58

在规则的 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'"

4

我想提供一个例子。虽然它可能不是直接回答用户的问题,但当我搜索类似的内容并尝试弄清如何运行多个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 进行安装,这是一个非常方便的命令。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接