Sign up ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

I would like to generate a random string (e.g. passwords, user names, etc.). It should be possible to specify the needed length (e.g. 13 chars).

What tools can I use?

share|improve this question

6 Answers 6

To generate a random password you can use pwgen:

pwgen generates random, meaningless but pronounceable passwords. These passwords contain either only lowercase letters, or upper and lower case mixed, or digits thrown in. Uppercase letters and digits are placed in a way that eases remembering their position when memorizing only the word.

Generate 7 passwords of length 13:

geek@liv-inspiron:~$ pwgen 13 7
Eu7Teadiphaec giepahl3Oyaiy iecoo9Aetaib4 phaiChae6Eivi athoo3igee8Co
Iphu4ufeDeelo aesoYi2lie9he 

As mentioned in the comments, you can avoid reducing entropy by using the -s argument (i.e. generate more secure, completely random but hard to remember passwords):

geek@liv-inspiron:~$ pwgen -s 13 7
eAfycrPlM4cYv 4MRXmZmyIVNBp D8y71iqjG7Zq7 FQRHcserl4R8O yRCUtPtV3dsqV
0vJpp2h0OrgF1 QTp7MKtJyTrjz 

To generate random user names you can use gpw:

This package generates pronounceable passwords. It uses the statistics of three-letter combinations (trigraphs) taken from whatever dictionaries you feed it.

Generate 7 passwords (user names) of length 13:

geek@liv-inspiron:~$ gpw 7 13
sreepoidahsas
risadiestinge
ntodynesssine
deodstestress
natinglumperm
riasigentspir
enderiferback
share|improve this answer
3  
+1 for not reinventing the wheel. If you don't want the reduced entropy of the "pronounceable" constraint, simply use pwgen -s. –  Nate Eldredge 19 hours ago

My favorite way to do it is by using /dev/urandom together with tr to delete unwanted characters for instance to get only numbers and letters:

head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13
share|improve this answer
    
Interesting. How do you control length with this approach? –  landroni yesterday
7  
Or do this: head /dev/urandom | tr -dc A-Za-z0-9 | head -c10 - This way is more accurate. You get 10 characters that are capitals, lowers, or digits –  Brandin yesterday
1  
@landroni To add the \n in the output you'll probably have to add it yourself. Here's a simple bash syntax shell function - make it a shell script if you want: function genPass() { N=${1:-8}; head /dev/urandom | tr -dc A-Za-z0-9 | head -c$N; echo ""; } –  Brandin yesterday
1  
@landroni Or if you want an easier one-liner, use echo with backticks to generate the \n for you: echo "$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c10)" –  Brandin yesterday
1  
The first head command might be problematic. It will output the first 10 lines from /dev/urandom, which means it will stop once it has seen the 10th newline. So the length of the output send to the tr command is random. It is possible that there will be less than 13 characters in the output from tr. I haven't computed the probability of this happening, the calculations are a bit tricky. –  kasperd 13 hours ago

@Brandin explained in a comment to another answer how to get at most 100 bytes from /dev/urandom using head -c 100. Another way to do this is with dd:

tr -dc A-Za-z0-9 < /dev/urandom | dd bs=100 count=1 2>/dev/null

The 2>/dev/null at the end of the dd command is to suppress the "... records in / ... records out" output.

I'm not aware of any substantial advantages/disadvantages between these two methods.

One issue with both methods is that the implementation of tr on my machine is choking with raw input from /dev/urandom. It needs to first be filtered to text-looking characters only. Here's a way to do that:

iconv -c -t US /dev/urandom | tr -dc A-Za-z0-9 | dd bs=100 count=1 2>/dev/null

(Unlike tr, iconv accepts a filename argument, so we can say just /dev/urandom instead of < /dev/urandom.)

share|improve this answer
    
For some reason the iconv solution maxes one CPU core and doesn't yield an output (I waited some 10s before killing it)... –  landroni yesterday
    
That's odd, maybe it's your version of iconv. Works here on multiple setups (OS X 10.10.x, libiconv 1.14 and libiconv 1.11; Linux 3.12.x and libiconv 1.11). –  dubiousjim yesterday
    
On my Ubuntu 14.04 system iconv is provided by libc-bin 2.19. I'm not sure if it's the same iconv... –  landroni 22 hours ago
    
tr supports binary input. However a range like A-Z may be influenced by locale settings. Try LC_ALL=C tr … –  Gilles 15 hours ago

Here is how, I do it. It generates 10 characters random string. You can optimize it by replacing the "fold", with other string processing tools.

cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 10 | head -n 1
share|improve this answer
    
+1 I like this approach, thanks. Allows to control both length and number of generated strings. –  landroni 5 hours ago

Depending on the level of randomness you want, you could simply go with bash's (also zsh and ksh, possibly others) builtin $RANDOM variable:

$ echo $RANDOM | tr '[0-9]' '[a-zA-Z]'
bfeci
$ echo $RANDOM | tr '[0-9]' '[a-zA-Z]'
cijjj

The methods reading directly from /dev/urandom are far simpler, but for the sake of completion, you could also use $RANDOM:

echo $(for((i=1;i<=13;i++)); do printf '%s' "${RANDOM:0:1}"; done) | tr '[0-9]' '[a-zA-Z]'
share|improve this answer
    
How do you control the length of the generated string? –  landroni 22 hours ago
    
@landroni I don't think you can short of using a loop until you get the right length. $RANDOM will print a number between 0 and 32767. –  terdon 22 hours ago
    
I've tried running the command some 20 times, and I can never get anything longer than 4-5 chars... –  landroni 22 hours ago
    
@landroni yes, that's what I said, it generates numbers between 0 and 32767, so 5 digits will be the max. If you need longer ones or need to be ab;e to specify the length, please edit your question and make that clear. –  terdon 21 hours ago
1  
@landroni thanks, I've added a way to specify length but it's not very good. I'd just use something like rand=$(head -c 100 /dev/urandom | tr -dc A-Za-z0-9 | head -c13) instead. –  terdon 19 hours ago

A super easy and simple (probably more simple than you're looking for) way to achieve this would be to generate a random number in a given range, convert that number to its equivalent ASCII character, and append it to the end of a string.

Here's a basic example in Python:

import random # import random library  
passFile = open("passwords.txt", 'w') # create file passwords.txt
passNum = int(input("Number of passwords: ")) # get number of  passwords
passLength = int(input("Password length: ")) # get length of passwords  
for i in range(passNum):
    password = "" # reset password
    for i in range(passLength):
        num = random.randint(65, 122) # get random number
        while num in range(91, 97): # Don't include punctuation
            num = random.randint(65, 122)
        password += chr(num) # add character to current password 
    passFile.write(password + "\n") # add current password to file  
passFile.close() # close file

EDIT: added comments, and added code to generate multiple passwords and write them to a file

share|improve this answer
1  
If given the power of Python I would NOT do it in this fashion. It would be much easier to use a join on a string containing all characters valid for a password and using random to select out the characters. –  Mike McMahon 6 hours ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.