Search code examples
shellsnakemake

Recommended way to do multiple shell commands with shell()


In snakemake, what is the recommended way to use the shell() function to execute multiple commands?


Solution

  • You can call shell() multiple times within the run block of a rule (rules can specify run: rather than shell:):

    rule processing_step:
        input:
            # [...]
        output:
            # [...]
        run:
            shell("somecommand {input} > tempfile")
            shell("othercommand tempfile {output}")
    

    Otherwise, since the run block accepts Python code, you could build a list of commands as strings and iterate over them:

    rule processing_step:
        input:
            # [...]
        output:
            # [...]
        run:
            commands = [
                "somecommand {input} > tempfile",
                "othercommand tempfile {output}"
            ]
            for c in commands:
                shell(c)
    

    If you don't need Python code during the execution of the rule, you can use triple-quoted strings within a shell block, and write the commands as you would within a shell script. This is arguably the most readable for pure-shell rules:

    rule processing_step:
        input:
            # [...]
        output:
            # [...]
        shell:
            """
            somecommand {input} > tempfile
            othercommand tempfile {output}
            """
    

    If the shell commands depend on the success/failure of the preceding command, they can be joined with the usual shell script operators like || and &&:

    rule processing_step:
        input:
            # [...]
        output:
            # [...]
        shell:
            "command_one && echo 'command_one worked' || echo 'command_one failed'"