Jon.Stromer.Galley Jon.Stromer.Galley - 5 months ago 12x
Ruby Question

How to list files given path with poorly escaped Windows separator

I'm attempting to do this:


but that is failing. I understand why, but I seem to lack the Ruby prowess to work around it.

I am given the path in a variable and otherwise have no control over it. Nor do I know the contents ahead of time.

Is there a way to make Dir function with double quoted strings that are poorly escaped? Alternatively, how does one take a variable with the apparent contents


and convert it into


This problem at the core seems to be how to potentially escape a string that should have been escaped but now is not.

The end result is I am not able to use the given string to do this as conceptually simple as

If given
then I have no problem. I can fix that:

foo = 'c:\temp\*.*'.gsub('\\', '/')

If given
then I have no problem. I can fix that:

foo = "c:\\temp\\*.*".gsub("\\", "/")

However, I am passed neither of those, but rather
. This string contains a TAB and a second undefined escape. It is this that I can't fix in a general way.

Even if I knew the contents ahead of time I am stumped on how to properly escape and transform this. I should add that I am not a ruby programmer at the moment so maybe there is some simple method to deal with this that I am not aware of.

I tried a bunch of stuff like:

"c:\temp\*.*".gsub("\t", "/t")

which gets me part of the way, but since the actual contents of the string are not known to me ahead of time this is a little wonky. Further, if the escape character is not valid as in
then I am also in a jam. So this also fails:

"c:\temp\*.*".gsub("\t", "/t").gsub("\*", "/*")


Is there a way to make Dir function with double quoted strings that are poorly escaped?


Garbage in, garbage out. There is no Rumpelstiltskin routine that returns gold when given trash.

Ruby auto-converts forward-slashes in filenames/paths to reverse-slashes when running on Windows. Simply make it a habit of using forward, *nix-style, slashes and you'll be fine.

From the IO documentation:

Ruby will convert pathnames between different operating system conventions if possible. For instance, on a Windows system the filename "/gumby/ruby/test.rb" will be opened as "\gumby\ruby\test.rb". When specifying a Windows-style filename in a Ruby string, remember to escape the backslashes:


I don't have "c:\temp" I have "c:\temp" as input

In a properly defined Windows path you should see:

'c:' + '\temp' + '\*.*' # => "c:\\temp\\*.*"

Note that the single-quotes are treating "\t" as an escaped-escape + "t". Your source for the variable is creating the string improperly by using double-quotes:

'c:' + "\temp" + "\*.*" # => "c:\temp*.*"

If you have "\t", you have a TAB character. It's possible to change it to an escaped-T using:

"c:\temp" # => "c:\temp"
"c:\temp"[2] # => "\t"
"c:\temp"[2].ord # => 9

'\t' # => "\\t"

"c:\temp".sub("\t", '\t') # => "c:\\temp"

The next problem is what to do when you have a String containing "*" to convert it to "\*". There's no way to search for "\*" because that's the same as "*" as seen above:

"\*.*" # => "*.*"

But, since "*.*" is a fairly specific "anything" wildcard, maybe simply searching for and replacing that pattern would work:

"c:\temp\*.*".gsub('*.*', '\\*.*') # => "c:\temp\\*.*"


"c:\temp\*.*".gsub('*.*', '/*.*') # => "c:\temp/*.*"

Back to dealing with "\t" and putting it all together... I'd start with:

"c:\temp\*.*".gsub("\t", '\t').gsub('*.*', '/*.*') # => "c:\\temp/*.*"
"c:\temp\*.*".gsub("\t", '/t').gsub('*.*', '/*.*') # => "c:/temp/*.*"

You'll have to figure out what to do if you have something like:


where they mean they want all files starting with file. Since you're seeing ambiguous inputs it seems the input routine needs to be more rigorous to not allow reversed-slashes.