# Generating a semi-random, but legal, filename

**URL:** <https://www.ruby-forum.com/t/generating-a-semi-random-but-legal-filename/148834>\
**Category:** Ruby\
**Created:** [September 17, 2008, 3:45pm UTC](https://www.ruby-forum.com/t/generating-a-semi-random-but-legal-filename/148834 "2008-09-17T15:45:43Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [September 17, 2008, 3:45pm UTC](https://www.ruby-forum.com/t/generating-a-semi-random-but-legal-filename/148834/1 "2008-09-17T15:45:43Z")

</div>

Hi everyone,

I thought this would be a fun brain teaser. In short, I need a way to  
generate a semi-random file name based on a template on MS Windows.  
The motivation, in case you’re wondering, is that I’m implementing a  
pure Ruby version of the mkstemp() function, which MS Windows does not  
support.

The rules:

1 - The template itself must be a legal MS Windows file name  
2 - The template must end with at least six ‘X’ characters. Raise an  
error otherwise.  
3 - All ‘X’ characters should be replaced with a (semi) random  
character  
4 - All replaced characters must be legal filename characters on MS  
Windows

For example, my\_template\_XXXXXX would become my\_template\_T$#z%Ya

What’s a legal filename on Windows? To keep it simple, we’ll just  
worry about these three rules:

- The following characters are illegal: \< \> : " / \ | ? \*
- Characters whose integer representations are in the range from zero  
through 31 are not allowed.
- Cannot end with a space

In case that first point is difficult to read on your browser, the  
explicitly illegal characters are greater than, less than, colon,  
forward slash, backslash, pipe, question mark and asterisk.

Good luck!

Dan

- Details for legal file names at  
[Naming Files, Paths, and Namespaces - Win32 apps | Microsoft Learn](http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx)
- Details for mkstemp at  
[mkstemp](http://www.opengroup.org/onlinepubs/009695399/functions/mkstemp.html)

---

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [September 17, 2008, 3:59pm UTC](https://www.ruby-forum.com/t/generating-a-semi-random-but-legal-filename/148834/2 "2008-09-17T15:59:35Z")

</div>

> I thought this would be a fun brain teaser. In short, I need a way to  
> generate a semi-random file name based on a template on MS Windows.  
> The motivation, in case you’re wondering, is that I’m implementing a  
> pure Ruby version of the mkstemp() function, which MS Windows does not  
> support.

Aside, for those who aren’t aware, there is tempfile.rb in the Ruby  
standard library which does something similar: i.e. create a random name  
from a template, then open the file.

The names it generates aren’t really random, but AFAICT are guaranteed  
to be unique. The documentation for mkstemp doesn’t make any claims to  
randomness either though.

---

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [September 17, 2008, 6:27pm UTC](https://www.ruby-forum.com/t/generating-a-semi-random-but-legal-filename/148834/3 "2008-09-17T18:27:46Z")

</div>

2008/9/17 Daniel B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> Hi everyone,
> 
> I thought this would be a fun brain teaser. In short, I need a way to  
> generate a semi-random file name based on a template on MS Windows.  
> The motivation, in case you’re wondering, is that I’m implementing a  
> pure Ruby version of the mkstemp() function, which MS Windows does not  
> support.

To be fair, MS Windows supports \_mktemp() function.  
mkstemp() can be defined as

def mkstemp(p)  
require ‘Win32API’  
\_mktemp = Win32API.new(“msvcrt”, “\_mktemp”, ‘P’, ‘P’)  
File.open(\_mktemp.call(‘my\_template\_XXXXXX’),File::CREAT|File::EXCL)  
end

Regards,

Park H.

---

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [September 17, 2008, 9:37pm UTC](https://www.ruby-forum.com/t/generating-a-semi-random-but-legal-filename/148834/4 "2008-09-17T21:37:34Z")

</div>

Actually, this might be a bit cleaner:

def randomFileNameSuffix (numberOfRandomchars)  
s = “”  
numberOfRandomchars.times { s \<\< (65 + rand(26)) }  
s  
end

puts “foo\_” + randomFileNameSuffix(7) + “.txt”

=\> foo\_OLNMGZZ.txt

Note: the 65 added is the numeric value of “A”. rand(26) gives 0…25.  
So, we add that to a capital “A” to get the random letter.

It is rather simple but that is not always a defect.

---

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [September 17, 2008, 9:01pm UTC](https://www.ruby-forum.com/t/generating-a-semi-random-but-legal-filename/148834/5 "2008-09-17T21:01:49Z")

</div>

Daniel B. wrote:

> For example, my\_template\_XXXXXX would become my\_template\_T$#z%Ya

How about this:

def getRandLetter  
65 + rand(26)  
end

def randomFileNameSuffix (baseFileName, numberOfRandomchars)  
numberOfRandomchars.times { baseFileName \<\< getRandLetter }  
baseFileName  
end

fn = randomFileNameSuffix(“foo\_”, 7)  
puts fn

---

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [September 18, 2008, 4:10am UTC](https://www.ruby-forum.com/t/generating-a-semi-random-but-legal-filename/148834/6 "2008-09-18T04:10:29Z")

</div>

On Sep 17, 1:30 pm, Lloyd L. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> =\> foo\_OLNMGZZ.txt
> 
> Note: the 65 added is the numeric value of “A”. rand(26) gives 0…25.  
> So, we add that to a capital “A” to get the random letter.
> 
> It is rather simple but that is not always a defect.

Simple, effective. Looks good to me!

Regards,

Dan
