I'm trying to create passwords using the following snippet to match a custom password policy. I've added three gtr statements, at the end of the string, to guarantee my password policy is met.

foo=$(gtr -dc 'a-zA-Z0-9' < /dev/urandom | head -c 96; gtr -dc 'A-Z' < /dev/urandom | head -c 1; gtr -dc 'a-z' < /dev/urandom | head -c 1; gtr -dc '0-9' < /dev/urandom | head -c 1); echo$foo


Could this code be simplified?

• What does the gtr command do? – 200_success Nov 29 '17 at 1:47
• The gtr command is the same as tr in Linux, just a Mac specific one that is installed through brew install coreutils – TheAuzzieJesus Nov 29 '17 at 1:56

I don't understand why you need GNU tr for this task. The macOs tr should work equally well.

For passwords, you should use /dev/random instead of urandom.

It's a funny password policy if it really requires the password to be 99 characters long. At that length, it doesn't matter anymore whether the password contains a digit or not because such a long password, if generated by a strong random generator, cannot be guessed.

The code in itself is fine. I would indent it differently, though, lining up all four calls to tr. Writing a function to eliminate the code duplication is probably overkill.

On top of @Roland's review, I recommend to move the repeated logic of getting n random characters to a function.

chars() {
local chars=$1 local count=$2
gtr -dc "$chars" < /dev/random | head -c "$count"
}

chars a-zA-Z0-9 96
chars A-Z 1
chars a-z 1
chars 0-9 1


Having common logic in a function makes it easier to maintain the code. For example, following Roland's suggestion to use /dev/random instead of /dev/urandom, you can make the change in one place, instead of many.

And now I also see why you needed to use gtr instead of tr. The BSD version of tr in OSX would complain about illegal byte sequences.