RetroPie forum home
    • Recent
    • Tags
    • Popular
    • Home
    • Docs
    • Register
    • Login

    shell scripting topic

    Scheduled Pinned Locked Moved Ideas and Development
    shellshell scriptprogramming
    191 Posts 10 Posters 83.3k Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • hiulitH
      hiulit @mitu
      last edited by

      @mitu I'm sorry, I didn't explain myself clearly enough.

      I already have a -h option that shows all the options available. What I meant is, how should I tell the user that the option --create-fun-fact can have:

      • no options
      • 1 option [system]
      • 2 options [system rom]

      That's what I've come up with: --create-fun-fact [] [system] [system rom]
      Is that correct?

      Did I explain myself better this time? :P

      My little contributions to the RetroPie project:

      • Shell-Script-Boilerplate
      • Fun-Facts-Splashscreens
      • Limit-Last-Played-Games
      mituM meleuM 2 Replies Last reply Reply Quote 0
      • mituM
        mitu Global Moderator @hiulit
        last edited by

        @hiulit said in shell scripting topic:

        --create-fun-fact [] [system] [system rom]

        Ah, ok. I think the correct syntax would be

        --create-fun-fact [SYSTEM] [ROM]
        

        Usually an argument in brackets ([arg]) means the argument is optional.

        hiulitH 1 Reply Last reply Reply Quote 0
        • hiulitH
          hiulit @mitu
          last edited by

          @mitu I see! And if an argument is NOT optional? I have some of those around :P

          My little contributions to the RetroPie project:

          • Shell-Script-Boilerplate
          • Fun-Facts-Splashscreens
          • Limit-Last-Played-Games
          mituM 1 Reply Last reply Reply Quote 0
          • mituM
            mitu Global Moderator @hiulit
            last edited by

            @hiulit If it's not optional, just remove the brackets.

            --create-fun-fact system [rom]
            
            1 Reply Last reply Reply Quote 0
            • meleuM
              meleu @hiulit
              last edited by meleu

              @hiulit can you explain the use case and provide some examples?

              I'm sure we can find ways to make an option have zero, one or two options, but from a user point of view I think it's a bit confusing.

              EDIT:
              I can't see what would be the use for --create-fun-fact system rom, but if it's intended to be used on RetroPie, you can detect the system by looking the directory where the rom is located.

              • Useful topics
              • joystick-selection tool
              • rpie-art tool
              • achievements I made
              hiulitH 1 Reply Last reply Reply Quote 0
              • hiulitH
                hiulit @meleu
                last edited by

                @meleu I'll try to explain myself even better than the last time :P Here we go!

                This all comes from the fun-facts-splashscreens-runcommand-onend.sh that has these lines:

                SYSTEM="$1"
                ROM_PATH="$3"
                sudo "$SCRIPT_DIR/fun-facts-splashscreens.sh" --create-fun-fact "$SYSTEM" "ROM_PATH"
                

                This is what creates the launching images when stoping the game. This is something the user doesn't need to care about. But then I already had --create-fun-fact in the help message so I wanted to let the user use it, like this:

                • --create-fun-fact with no options passed creates a boot splashscreen.
                • --create-fun-fact [SYSTEM] (SYSTEM can be all or any RetroPie system) creates launching images for all the systems, or the given system with the system's logo (and console if it exists).
                • --create-fun-fact [SYSTEM] [ROM] (ROM can be an absolute path or just the ROM's name + ext, and then it takes the given system to look for the path) creates a launching image for the game.

                Examples:

                • --create-fun-fact
                • --create-fun-fact all
                • --create-fun-fact megadrive
                • --create-fun-fact megadrive "/home/RetroPie/megadrive/Sonic the Hedgehog.zip"
                • --create-fun-fact megadrive "Sonic the Hedgehog.zip"

                I can see that from the user's perspective it could be a little confusing... Maybe it's better to split --create-fun-fact into two separate functions --create-fun-fact-boot-splashscreen and --create-fun-fact-launching-images.

                Maybe I should remove this option from the help message? Just have it for myself to test?
                That's something that can be done via the GUI, btw:

                0_1522918743191_2018-04-03-181738_727x465_scrot.png

                1_1522918743201_2018-04-03-181800_727x465_scrot.png

                My little contributions to the RetroPie project:

                • Shell-Script-Boilerplate
                • Fun-Facts-Splashscreens
                • Limit-Last-Played-Games
                meleuM 1 Reply Last reply Reply Quote 0
                • meleuM
                  meleu @hiulit
                  last edited by

                  @hiulit You wouldn't want to create a launching image for Sonic using a NES splashscreen, would you? Well, my suggestion below does not have this kind of flexibility, but here it go:

                  help message

                  --create-fun-fact [system|path/to/a/ROM]     no arguments = create boot splashscreen
                                                               system = create a launching image for system
                                                               ROM = create a launching image for a ROM
                  

                  If you wanna use this approach, please write a better help message for this option! ;)

                  code

                  #!/bin/bash
                  
                  user="$SUDO_USER"
                  [[ -z "$user" ]] && user="$(id -un)"
                  home="$(eval echo ~$user)"
                  
                  readonly RP_DIR="$home/RetroPie"
                  readonly RP_ROMS_DIR="$RP_DIR/roms"
                  readonly RP_CONFIG_DIR="/opt/retropie/configs"
                  
                  function get_options() {
                  
                      case "$1" in
                  
                  #H --create-fun-fact [system|path/to/a/ROM]     no arguments = create boot splashscreen
                  #H                                              system = create a launching image for system
                  #H                                              ROM = create a launching image for a ROM
                          --create-fun-fact)
                              if [[ -z "$2" ]]; then
                                  # NOTE: for this usecase the --create-fun-fact MUST be the
                                  #       last parameter used in the command line.
                                  echo "Let's create a boot splashscreen with a fun fact!"
                  
                              elif [[ -f "$2" ]]; then
                                  # NOTE: if it's a regular file, let's check if it's a ROM and
                                  #       create a splashscreen for this game.
                                  local rom_full_path="$(realpath "$2")"
                  
                                  if [[ "$rom_full_path" != "$RP_ROMS_DIR"* ]]; then
                                      echo "ERROR: \"$2\" is not on a valid ROM directory" >&2
                                      exit 1
                                  fi
                  
                                  # Reference for the tricks used to get the system's name below:
                                  # http://www.tldp.org/LDP/abs/html/parameter-substitution.html#PSOREX2
                                  system="${rom_full_path#$RP_ROMS_DIR/}"
                                  system="${system%/*}"
                  
                                  echo "Let's create a launching image for \"$2\" using the ${system}'s one!"
                  
                              elif [[ -d "$RP_CONFIG_DIR/$2" ]]; then
                                  echo "Let's create a launching image for \"$2\" system!"
                  
                              else
                                  echo "ERROR: \"$2\": invalid argument." >&2
                                  exit 1
                              fi
                              ;;
                  
                  #H --help                                       Print the help message and exit.
                          --help|-h)
                              sed '/^#H /!d; s/^#H //' "$0"
                              echo
                              exit 0
                              ;;
                      esac
                  }
                  
                  get_options "$@"
                  

                  testing

                  $ ./cff.sh --create-fun-fact
                  Let's create a boot splashscreen with a fun fact!
                  
                  $ ./cff.sh --create-fun-fact abcd
                  ERROR: "abcd": invalid argument.
                  
                  $ ./cff.sh --create-fun-fact nes
                  Let's create a launching image for "nes" system!
                  
                  $ ./cff.sh --create-fun-fact ~/RetroPie/roms/nes
                  ERROR: "/home/meleu/RetroPie/roms/nes": invalid argument.
                  
                  $ ./cff.sh --create-fun-fact ~/RetroPie/roms/nes/Contra\ \(USA\).zip 
                  Let's create a launching image for "/home/meleu/RetroPie/roms/nes/Contra (USA).zip" using the nes's one!
                  
                  • Useful topics
                  • joystick-selection tool
                  • rpie-art tool
                  • achievements I made
                  hiulitH 1 Reply Last reply Reply Quote 0
                  • hiulitH
                    hiulit @meleu
                    last edited by hiulit

                    @meleu Thanks for your reply! And no, I wouldn't want that

                    launching image for Sonic using a NES splashscreen
                    But my script prevents from doing that.

                    I'll try to paste every piece of code that I have, because it's very similar to what you have:

                    -cff|--create-fun-fact)
                        is_fun_facts_empty
                        if [[ -z "$2" ]]; then
                            create_fun_fact
                        else
                            shift
                            create_fun_fact "$@"
                            shift
                        fi
                        ;;
                    

                    If no arguments are passed called create_fun_fact without arguments, if there are any arguments, pass them all.

                    function create_fun_fact() {
                        if [[ -z "$1" ]]; then
                            create_fun_fact_boot
                        else
                            create_fun_fact_launching "$@"
                        fi
                    }
                    

                    There's more things going one here, but it basically calls one function or another depending on if there are arguments.
                    create_fun_fact_boot is self explanatory.
                    create_funfact_launching takes all the arguments and then:

                    function create_fun_fact_launching() {
                        local system="$1"
                        local rom_path="$2"
                    
                        if [[ "$system" == "all" ]]; then
                            // Loop all systems and call create_fun_fact_launching "$system"
                        else
                            if [[ -n "$rom_path" ]]; then
                                // Check if $system it's the same in "rom_path"
                                if true
                                    // Create launching image for the game
                                else
                                    // Create launching image for the system
                            else
                                // Create launching image for the system
                            fi
                        fi
                    }
                    

                    More or less that what I do. I think it's similar of what you wrote.

                    But then again, I think maybe it's better to to have 2 separate options:

                    • --create-fun-facts-boot-splashscreen(doesn't accept any argument)
                    • --create-fun-facts-launching-images (accepts system and rom)

                    EDIT:
                    You can take a look for youself https://github.com/hiulit/RetroPie-Fun-Facts-Splashscreens/blob/new-gui-menu/fun-facts-splashscreens.sh ;)

                    My little contributions to the RetroPie project:

                    • Shell-Script-Boilerplate
                    • Fun-Facts-Splashscreens
                    • Limit-Last-Played-Games
                    1 Reply Last reply Reply Quote 0
                    • meleuM
                      meleu
                      last edited by

                      I've just found this and decided to share here:

                      Pure Bash Bible

                      The goal of this book is to document known and unknown methods of doing various tasks using only built-in bash features. Using the snippets from this bible can help remove unneeded dependencies from scripts and in most cases make them faster.

                      • Useful topics
                      • joystick-selection tool
                      • rpie-art tool
                      • achievements I made
                      cyperghostC 1 Reply Last reply Reply Quote 2
                      • cyperghostC
                        cyperghost @meleu
                        last edited by cyperghost

                        @meleu Wow this is really helpfull ;) Cool snippets for bash coders. Thank you so much.

                        For ex:
                        Reverse array I did

                        for ((z=${#array[*]}-1; z>-1; z--)); do
                               echo "${array[z]}"
                        done
                        

                        Reverse array with the bash-bible

                        ## Reverse an array
                        
                        # ```sh
                        reverse_array() {
                            # Usage: reverse_array "array"
                            shopt -s extdebug
                            f()(printf '%s\n' "${BASH_ARGV[@]}"); f "$@"
                            shopt -u extdebug
                        }
                        # ```
                        

                        Up to now my version seems a bit less complex. Maybe it's due my limited coding skills. I'm still learning ....

                        1 Reply Last reply Reply Quote 0
                        • cyperghostC
                          cyperghost
                          last edited by cyperghost

                          @meleu I think that's just a note to me ... BashPitfalls

                          function1(){
                              local status=$(false)
                              echo $?
                          }
                          

                          Will return 0 which is obviously wrong
                          So the return code 0 just indicates the correct setting of a local setted value, which was correctly done ;)

                          So to get out of this make following

                          function1(){
                              local status
                              status=$(false)
                              echo $?
                          }
                          

                          This will put out correct value for "error" 1

                          That's all folks

                          meleuM 1 Reply Last reply Reply Quote 1
                          • meleuM
                            meleu @cyperghost
                            last edited by

                            @cyperghost yeah, that's a thing to be careful. I learned it while reading the RetroPie's Shell Style Guide: https://retropie.org.uk/docs/Shell-Style-Guide/#use-local-variables

                            • Useful topics
                            • joystick-selection tool
                            • rpie-art tool
                            • achievements I made
                            1 Reply Last reply Reply Quote 0
                            • meleuM
                              meleu
                              last edited by

                              I would like to share a little trick I learned today and also ask for some help...

                              First the short story

                              I was needing to check if the current hour is after 18h, then I tried this:

                              hour=$(date +%H)
                              if [[ $hour -gt 18 ]]; then
                                  echo "do something..."
                              fi
                              

                              And then I got this error (please, forgive the non-english):

                              -bash: [[: 08: valor muito grande para esta base de numeração (token de erro é "08")
                              

                              As you can see, the problem is that date +%H returns 08, and when I try to compare it, bash doesn't see 08 as a decimal number.

                              The solution is obviously getting rid of that leading zero. I decided that using sed would be overkill for such a simple task, then I've found a pure bash solution using a feature of $(( )).

                              hour=$(date +%H)
                              hour=$(( 10#$hour ))  # could also be an oneliner: $(( 10#$(date +%H) ))
                              if [[ $hour -gt 18 ]]; then
                                  echo "do something..."
                              fi
                              

                              And now my script is working perfectly!

                              Now the help I mentioned earlier on the beginning of this post...

                              On that stackoverflow answer I see this:

                              The $(( )) sets up an arithmetic context and the 10# converts the number from base 10 to base 10 causing any leading zeros to be dropped.

                              Alright, but I like to see stuff on the official documentation in a hope to learn more tricks. The $(( )) is a bash builtin feature, but in the official documentation there's no mention to the 10# operand.

                              Any thoughts on where to get info about it?

                              • Useful topics
                              • joystick-selection tool
                              • rpie-art tool
                              • achievements I made
                              SanoS 1 Reply Last reply Reply Quote 0
                              • SanoS
                                Sano @meleu
                                last edited by

                                @meleu That I can answer !
                                Actually it's in the very doc you mention :
                                https://www.gnu.org/software/bash/manual/bash.html#Shell-Arithmetic

                                Constants with a leading 0 are interpreted as octal numbers. A leading ‘0x’ or ‘0X’ denotes hexadecimal. Otherwise, numbers take the form [base#]n, where the optional base is a decimal number between 2 and 64 representing the arithmetic base, and n is a number in that base. If base# is omitted, then base 10 is used. When specifying n, the digits greater than 9 are represented by the lowercase letters, the uppercase letters, ‘@’, and ‘_’, in that order. If base is less than or equal to 36, lowercase and uppercase letters may be used interchangeably to represent numbers between 10 and 35.

                                meleuM 1 Reply Last reply Reply Quote 1
                                • meleuM
                                  meleu @Sano
                                  last edited by

                                  @sano whoops! Didn't catch those little words 😅

                                  Thanks Sano-san. And yeah, I learned more tricks!

                                  • Useful topics
                                  • joystick-selection tool
                                  • rpie-art tool
                                  • achievements I made
                                  SanoS 1 Reply Last reply Reply Quote 1
                                  • SanoS
                                    Sano @meleu
                                    last edited by

                                    @meleu Just FYI, you could just have used date +%-H ;)
                                    Glad to see you here again BTW !

                                    meleuM 1 Reply Last reply Reply Quote 1
                                    • meleuM
                                      meleu @Sano
                                      last edited by

                                      @sano ouch! Looks like I need RTFM some more...

                                      From the date man page:

                                             By default, date  pads  numeric  fields  with  zeroes.   The  following
                                             optional flags may follow '%':
                                      
                                             -      (hyphen) do not pad the field
                                      

                                      Thanks again, Sanso-sensei!

                                      • Useful topics
                                      • joystick-selection tool
                                      • rpie-art tool
                                      • achievements I made
                                      SanoS 1 Reply Last reply Reply Quote 1
                                      • SanoS
                                        Sano @meleu
                                        last edited by

                                        @meleu I really deserve no special credit for this, I just remembered something like this existed, probably had to use it in the past, too :)

                                        1 Reply Last reply Reply Quote 0
                                        • cyperghostC
                                          cyperghost
                                          last edited by cyperghost

                                          A common mistake is often made by using grep.
                                          It is often told that grep finds a total of all search strings within a text file due the -c switch. That is total nonsense .... -c just counts lines

                                          So we miss

                                          hello hello hello hello
                                          hello
                                          
                                          grep -c hello
                                          2
                                          

                                          We use a small hack ;)
                                          Better is to use the -o option is will show occourences of search string listed in newline and now we pipe to wc -l ... and count lines again - now we catched them all ;)

                                          hello hello hello hello
                                          hello
                                          
                                          grep -o hello | wc -l
                                          5
                                          
                                          1 Reply Last reply Reply Quote 0
                                          • cyperghostC
                                            cyperghost
                                            last edited by cyperghost

                                            @meleu

                                            EDIT BEGIN
                                            I think I found a good solution with pure bash
                                            But maybe some knows a better one ;)

                                            val=${#Unix[@]}
                                            for ((i=0; i<$val; i+=1)); do
                                            

                                            EDIT END


                                            Is there something that can be made easier (more efficient) than this script?
                                            I want to merge two arrys
                                            A1=(1 2 3)
                                            A2=(one two there)
                                            the result should be A3
                                            A3=(1 one 2 two 3 three)

                                            It works with this script.
                                            But first... I want to avoid any counters (if possible)
                                            Do you know a nice trick to count up values {0..6} works only with fixed characters not as variable. So {0..6} is fine {0..$arraysize} not

                                            #!/bin/bash
                                            # A small script to show how to merge two arrays
                                            # with alternating values (exp. for creating arrays for dialogs)
                                            
                                            # Example Array
                                            Unix=("Debian" "Red hat" "Ubuntu" "Suse" "Fedora" "UTS" "OpenLinux")
                                            Shell=("bash" "csh" "jsh" "rsh" "ksh" "rc" "tcsh")
                                            
                                            # Check if both arrays got some size
                                            [[ ${#Unix[@]} -eq ${#Shell[@]} ]] || exit 1
                                            echo "Both arrays got same size -- Proceed"
                                            
                                            val=$((${#Unix[@]}-1))
                                            echo $val
                                            for i in $(seq 0 $val); do
                                                echo "Merging ${Unix[$i]} and ${Shell[$i]}"
                                                UnixShell+=("${Unix[$i]}" "${Shell[$i]}")
                                            done
                                            
                                            echo "${UnixShell[@]}"
                                            
                                            meleuM 1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post

                                            Contributions to the project are always appreciated, so if you would like to support us with a donation you can do so here.

                                            Hosting provided by Mythic-Beasts. See the Hosting Information page for more information.