In addition to the various implementation optimizations in @slm's answer@slm's answer, there is a huge algorithmic optimization to make. (There may also be some cryptanalytic attacks, I'm not sure how strong the UNIX crypt algorithm is, but that is probably beyond the scope of a shell script)
The problem you're trying to solve was probably described as "brute force a password". In order to do that, you generated all possibilities in alphabetical order, and tested them, exiting at the first match. If you model a password as "random string of 5 characters", then this is actually optimal.
A few people will use an actually random password. A few, not most. Even for things where they really ought to. Especially for things they don't consider important. We've had this confirmed recently and repeatedly by numerous leaked password databases.
The password you're looking for could be dbKbuW. But it's many, many times more likely to be qwerty, abc123, or 123456. We know from the leaked databases that the top thousand or so most common passwords will crack most accounts.
So the real speed up is to generate your guesses in a better order. At minimum, sort your letter-lists by frequency in English (or, better yet, in passwords). You should be trying e a lot earlier than z. Run through a list of 1000 or so common passwords first, before even starting your brute-force iteration across the search space (wastes a little time if it doesn't work, but depending on your users it'll work well over half the time).
If you look at how actual password cracking tools work, they run through a few lists of common passwords, then through a dictionary, then through variations (e.g., "change e to 3"), then through various password generating strategies, and only if none of that works, then finally start iterating through the search space.