loopserror-handlingzshcracking

In zsh how do you make a loop that when the command FAILS, it retries the same command with new arguments until no error triggered


Some context on why I'm asking this question. I'm currently screwing around in python trying stuff out and I want to utilize the os.system() command to try different potential wifi passwords from a dictionary text file I have until it succeeds. I've attempted using python itself to look for errors using TRY/EXCEPT but I'm not experienced enough to know how to look for errors in another resource and dictate actions based on that. So at the time I THOUGHT the most simple method is to say the following:

for current_pass in PotentialPasswords:
    os.system('networksetup -setairportnetwork en0 {} "{}"'.format(ssid, current_pass))

Of course this is awful and caused lots of issues. I tried several variations on this until it dawned on me that zsh has looping capabilities itself and so right now I'm looking at if it is possible to effectively tell zsh to execute a command, and if that command fails, try that same command again but with new arguments, UNTIL the command succeeds, at which case I want the loop to end.

for x in pass1 pass2 pass3 pass4; do networksetup -setairportnetwork en0 NETWORK_NAME $x; done

I know the above does not work, but I hope that I'm at least on the right track. Any advice or guidance on how to accomplish my goal would be infinitely appreciated!


Solution

  • #!/bin/bash
    
    # Simulate an external command that randomly fails
    function external_command {
        if [ $[ $RANDOM % $1 ] -eq 0 ] ; then
            echo "succeed"
            return 0
        else
            echo "failed"
            return 1
        fi
    }
    
    # Iterate over your predefined tests
    for i in 2 3 4 5 ; do
        # Retry logic
        while
            echo -n "Trying external_command $i... "
            # Call the external command
            external_command $i
            # $? is the return code, 0 if successful
            [ $? -ne 0 ]
        do true ; done
    done
    

    Which gives an output such as this:

    Trying external_command 2... succeed
    Trying external_command 3... failed
    Trying external_command 3... succeed
    Trying external_command 4... failed
    Trying external_command 4... succeed
    Trying external_command 5... failed
    Trying external_command 5... failed
    Trying external_command 5... failed
    Trying external_command 5... failed
    Trying external_command 5... failed
    Trying external_command 5... failed
    Trying external_command 5... failed
    Trying external_command 5... succeed
    

    I borrowed the idea of the do..while loop from here.

    The solution should work in bash/zsh.