Search code examples
bashswitch-statementprogress

Run a series of tasks, but depending on progress start on task x in bash (continue switch case)


I have a series of tasks that run one after the other, but depending on the progress, that is saved in a variable it has to start at the appropriate step.

For instance, I have 5 tasks. Task 1 is supposed to start, followed by task 2, then task 3 and so on. But if the variable progress contains the value 2, it should start at task 2, continue with task 3 and so on.

I thought this would be achievable with a switch case, like:

case $progress in
    1)
        echo "Task1"
        $progress=2;;
    2)
        echo "Task2"
        $progress=3;;
    3)
        echo "Task3";;
    *)
        echo "null";;
esac

The problem here is that the switch case ends, after the first match. How do I have the switch case continue after the first match?


Solution

  • To complement boolean.is.null's own helpful answer, here's an overview of case-branch terminators:

    • ;; [the only option up to Bash 3.x]

      • Exit the case statement right away (from a matching branch).
    • ;& [Bash 4.0+]

      • Unconditionally fall through to the next branch - as in a C switch statement's case handler without break. Note that unconditional means that the very next branch is entered, no matter what its condition is.
    • ;;& [Bash 4.0+]

      • Continue evaluating branch conditions until another one, if any (including *)), matches.

    ;; example; outputs line one:

    case 1 in
      1)  # entered, because it matches and is the first condition
        echo 'one'
        ;;  # exits the `case` statement here
      ?)  # never entered
        echo 'any single char.'
        ;;
    esac
    

    ;& example (Bash 4.0+); outputs lines one and two:

    case 1 in
      1)  # entered, because it matches and is the first condition
        echo 'one'
        ;&  # fall through to very next branch
      2) # entered, because the previous branch matched and fell through
        echo 'two'
        ;;  # exits the `case` statement here
    esac
    

    ;;& example (Bash 4.0+); outputs line one and any:

    case 1 in
      1) # entered, because it matches and is the first condition
        echo 'one'
        ;;&  # continue evaluation branch conditions
      2) # not entered, because its condition doesn't match
        echo 'two'
        ;;
      *)  # entered, because it's the next *matching* condition
        echo 'any'
        ;; # using a terminator is optional in the * branch
    esac