<@ULVA73B9P> how do i run multiple cmd commands us...
# ask-marvin
a
@Marvin how do i run multiple cmd commands using ShellOperation?
m
thought for 133.6 seconds
Great question! In Prefect 3.x, use
ShellOperation
from the
prefect-shell
integration and pass a list of commands to the
commands
parameter. For Windows “cmd” specifically, set
shell="cmd"
(and optionally
extension=".cmd"
). Each list item becomes a line in a temporary script that Prefect runs. Key points: - Use
commands=[...]
(preferred) instead of cramming everything into one string with
&&
. - On Windows cmd, failed commands do not stop the script by default. To fail-fast, either chain with
&&
or add
|| exit /b 1
to each critical line. - Set
env
to pass environment variables and
working_dir
to change directories. - For Unix, set
shell="bash"
(or
sh
) and add
set -Eeuo pipefail
to stop on failures. Example: Windows cmd with multiple commands
Copy code
from prefect import flow
from prefect_shell.commands import ShellOperation

@flow
def run_cmd_script():
    op = ShellOperation(
        commands=[
            "echo Starting",
            "dir",
            "where python || exit /b 1",  # fail-fast if not found
            "echo Done"
        ],
        shell="cmd",
        extension=".cmd",                # ensures a .cmd script on Windows
        working_dir="C:\\path\\to\\repo",
        env={"MY_VAR": "value"},
        stream_output=True               # streams output to Prefect logs
    )
    op()  # execute

if __name__ == "__main__":
    run_cmd_script()
Example: Unix bash with multiple commands
Copy code
from prefect import flow
from prefect_shell.commands import ShellOperation

@flow
def run_bash_script():
    op = ShellOperation(
        commands=[
            "set -Eeuo pipefail",
            "echo Starting",
            "ls -la",
            "command_that_may_fail",
            "echo Done"
        ],
        shell="bash",
        extension=".sh",
        working_dir="/path/to/repo",
        env={"MY_VAR": "value"},
    )
    op()

if __name__ == "__main__":
    run_bash_script()
Notes on chaining: - You can also chain within a single command:
commands=["step1 && step2 && step3"]
. This is fine if you prefer explicit fail-fast chaining, but multiple list entries are usually more readable. - In cmd, to ensure the script stops on error when using one-command-per-line, add
|| exit /b 1
to lines that must cause failure. Docs: prefect-shell integration If you’re indeed targeting Windows cmd, the first example is the recommended setup. Want me to adapt it to your exact commands?