skip to Main Content

Hi I fork and customize (https://www.putorius.net/create-multiple-choice-menu-bash.html). It is part of automated building script for my project. I wonder how to redirect the answer to different lines (e.g Debian building script starts in line 20 etc.) instead splitting into various files?

#!/bin/sh
PS3='Choose your building platform: '
OS=("Debian" "Fedora" "Arch Linux" "Quit")
select fav in "${OS[@]}"; do
    case $fav in
        "Debian")
            /bin/sh debian.sh
            ;;
        "Fedora")
            /bin/sh fedora.sh
            ;;
        "Arch Linux")
            /bin/sh arch_linux.sh
            ;;

            "Quit")
            echo "Aborting..."
            exit
            ;;
       *) echo "invalid option $REPLY";;
    esac
done    

Because it comes handy that you can write the code in single file instead of splitting into multiple files.

3

Answers


  1. You can define shell functions:

    #!/bin/sh
    
    custom_function () {
       echo 'custom_function called !'
    }
    
    custom_function
    

    In your case you can define three different functions, one for each build target and then call them:

    #!/bin/sh
    
    target_debian () {
       echo 'debian'
    }
    target_fedora () {
       echo 'fedora'
    }
    target_arch () {
       echo 'arch'
    }
    
    PS3='Choose your building platform: '
    OS=("Debian" "Fedora" "Arch Linux" "Quit")
    select fav in "${OS[@]}"; do
        case $fav in
            "Debian")
                target_debian
                ;;
            "Fedora")
                target_fedora
                ;;
            "Arch Linux")
                target_arch
                ;;
    
                "Quit")
                echo "Aborting..."
                exit
                ;;
           *) echo "invalid option $REPLY";;
        esac
    done    
    

    Source: https://www.tutorialspoint.com/unix/unix-shell-functions.htm

    Login or Signup to reply.
  2. One approach is to set some flag. Something like:

    #!/usr/bin/env bash
    
    Arch_flag=0
    Debian_flag=0
    Fedora_flag=0
    
    PS3='Choose your building platform: '
    OS=("Debian" "Fedora" "Arch Linux" "Quit")
    select fav in "${OS[@]}"; do
      case $fav in
        "Debian")
          Debian_flag=1
          break
          ;;
        "Fedora")
          Fedora_flag=1
          break
          ;;
        "Arch Linux")
          Arch_flag=1
          break
          ;;
        "Quit")
          echo "Aborting..."
          exit
          ;;
        *) echo "invalid option $REPLY";;
      esac
    done
    
    
    if ((Debian_flag)); then
      printf 'Do something with %sn' Debian
    fi
    
    if ((Fedora_flag)); then
      printf 'Do something with %sn' Fedora
    fi
    
    if ((Arch_flag)); then
      printf 'Do something with %sn' Arch
    fi
    

    Or depending on the use case one can embed the flag in the loop.

    #!/usr/bin/env bash
    
    PS3='Choose your building platform: '
    OS=("Debian" "Fedora" "Arch Linux" "Quit")
    select fav in "${OS[@]}"; do
      Arch_flag=0
      Debian_flag=0
      Fedora_flag=0
    
      case $fav in
        "Debian")
          Debian_flag=1
          ;;
        "Fedora")
          Fedora_flag=1
          ;;
        "Arch Linux")
          Arch_flag=1
          ;;
        "Quit")
          echo "Aborting..."
          exit
          ;;
        *) echo "invalid option $REPLY";;
      esac
    
      if ((Debian_flag)); then
        printf 'Do something with %sn' Debian
      fi
    
      if ((Fedora_flag)); then
        printf 'Do something with %sn' Fedora
      fi
    
      if ((Arch_flag)); then
        printf 'Do something with %sn' Arch
      fi
    done
    
    Login or Signup to reply.
  3. I *VERY STRONGLY* encourage you to pay attention to William Pursell's comments, and use areop-enap’s functions solution, or Jetchisel’s simple blocks, both of which are quite straightforward and elegant. Do not fall into the trap of embedding for the sake of whimsy.

    If you want to include several files in one file, use a tool like tar. If it has to be an executable, try zip.


    There are, however, some (few) cases where being able to have a script completely contain an entire data file is useful.

    For those RARE times when another entire file needs to be encoded into your script, put the files in something like base64-encoding. Decode the ones you need to their own files at runtime, or even to a pipe. (Do NOT use offsets. I’ve had to deal with that nightmare…)

    The code below only parses the files it needs. If you ask for "perl" it won’t even hit the section with the embedded bash file. (I’m not sure of how the interpreter might pre-parse and optimize, but I don’t think this method will allocate retained memory the way assigning these to variables would.)

    The one advantage to this method is that it lets you embed arbitrary executables such as compiled C code right into the script, but that is at best a somewhat dubious advantage…

    $: ls -l
    total 1
    -rwxr-xr-x 1 paul 1049089 398 Dec 12 08:54 tst
    
    $: for arg in bash perl; do ./tst $arg; done
    ./file1_bash this is the bash file
    ./file2_perl this one is perl
    
    $: ls -l
    total 3
    -rwxr-xr-x 1 paul 1049089  62 Dec 12 08:56 file1_bash
    -rwxr-xr-x 1 paul 1049089  51 Dec 12 08:56 file2_perl
    -rwxr-xr-x 1 paul 1049089 398 Dec 12 08:54 tst
    
    $: cat file1_bash
    #! /usr/bin/bash
    echo "${BASH_SOURCE:-$0}" "$@"
    
    $: cat file2_perl
    #! /usr/bin/perl
    print join ' ', $0, @ARGV, "n";
    
    $: cat tst
    #! /usr/bin/bash
    case $1 in
    bash) base64 -d <<< "
    IyEgL3Vzci9iaW4vYmFzaAplY2hvICIke0JBU0hfU09VUkNFOi0kMH0iICIkQCIgCg==
    " > file1_bash && chmod +x ./file1_bash && ./file1_bash this is the bash file ;;
    perl) base64 -d <<< "
    IyEgL3Vzci9iaW4vcGVybApwcmludCBqb2luICcgJywgJDAsIEBBUkdWLCAiXG4iOyAK
    " > file2_perl && chmod +x ./file2_perl && ./file2_perl this one is perl      ;;
    esac
    

    There are a lot of other issues to address –

    • it can take a lot of time to decode big files, though scripts should be ok
    • if you are dealing with various OS’s, be careful about paths, syntax, etc
    • make sure you properly copy the base64 into your file without corruption such as indentation
    • make sure the target system has the right tools to decode and run the scripts
    • ensure proper file locations and permissions when created
    • consider cleaning up after yourself if you don’t need to leave them for later use

    You get the idea.

    For the record, in case it matters, this was done on GitBash under windows. Your version might have to make a few refinements.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search