def run_bash_jobs(
    jobs: Iterator[Job], directory: PathLike = Path.cwd(), dry_run: bool = False
) -> None:
    """Submit commands to the bash shell.

    This function runs the commands iteratively but handles errors in the
    same way as with the pbs_commands function. A command will run for all
    combinations of variables in the variable matrix, however if any one of
    those commands fails then the next command will not run.

    """
    logger.debug("Running commands in bash shell")
    # iterate through command groups
    for job in jobs:
        # Check shell exists
        if shutil.which(job.shell) is None:
            raise ProcessLookupError(f"The shell '{job.shell}' was not found.")

        failed = False
        for command in job:
            for cmd in command:
                logger.info(cmd)
                if dry_run:
                    print(f"{job.shell} -c '{cmd}'")
                else:
                    result = subprocess.run(
                        [job.shell, "-c", f"{cmd}"], cwd=str(directory)
                    )
                    if result.returncode != 0:
                        failed = True
                        logger.error("Command failed: %s", command)
                        break
        if failed:
            logger.error("A command failed, not continuing further.")
            return
Submit commands to the bash shell.

    This function runs the commands iteratively but handles errors in the
    same way as with the pbs_commands function. A command will run for all
    combinations of variables in the variable matrix, however if any one of
    those commands fails then the next command will not run.