Project

General

Profile

Feature #8258

Dir#escape_glob

Added by Steve Klabnik about 3 years ago. Updated almost 2 years ago.

Status:
Open
Priority:
Normal
Assignee:
-
[ruby-core:54207]

Description

This is inspired by https://github.com/rails/rails/issues/6010.

Basically, if you do a Dir.glob in a directory whose name contains a glob character, things break. It would be nice to have a method which would escape the input so that we can Dir.glob inside of those directories.

History

#1 [ruby-core:54227] Updated by Konstantin Haase about 3 years ago

File.fnmatch_escape would make more sense, imo.

#2 [ruby-core:54236] Updated by Charles Nutter about 3 years ago

rkh (Konstantin Haase) wrote:

File.fnmatch_escape would make more sense, imo.

But it would be harder to remember when what you want is "glob" :-)

Why not just {Dir,File}.quote or .escape, to match Regexp.quote/escape? I would vote for File.escape, a method that escapes any file path to make it suitable for globbing.

#3 [ruby-core:54248] Updated by Steve Klabnik about 3 years ago

I don't feel strongly about the name, specifically.

#4 [ruby-core:54263] Updated by Benoit Daloze about 3 years ago

headius (Charles Nutter) wrote:

rkh (Konstantin Haase) wrote:

File.fnmatch_escape would make more sense, imo.

But it would be harder to remember when what you want is "glob" :-)

Why not just {Dir,File}.quote or .escape, to match Regexp.quote/escape? I would vote for File.escape, a method that escapes any file path to make it suitable for globbing.

I agree, this would be strictly superior.

I guess the most common use case is globbing on a directory recursively, so only the base directory is to be escaped, but this is not worth a specific method I think and could be done easily: Dir.glob("#{Dir.escape dir}//*.rb") { |file| ... }
Pathname could likely avoid this problem nicely in this situation: dir = Pathname("some_dir"); dir.glob("
/*.rb") { |file| ... }

#5 [ruby-core:54265] Updated by Benoit Daloze about 3 years ago

What is more worrying is implementations differ quite a bit in treating \ as an escape for these glob characters ({,},[,],*,?).

From my tests:
- MRI handle them fine
- Rubinius does not handle escaped [, { and }.
- JRuby does not handle escaped and

If I am not mistaken, escaping is as simple as: dir.gsub(/[|]|*|\?|{|}/, '\\' + '\0').

#6 [ruby-core:54266] Updated by Konstantin Haase about 3 years ago

  • Rubinius does not handle escaped [, { and }.
  • JRuby does not handle escaped [ and ]

These are implementation bugs, imo, and nothing to worry about here.

If I am not mistaken, escaping is as simple as: dir.gsub(/[|]|*|\?|{|}/, '\\' + '\0').

Yes, but it shifts responsibility for keeping this up to date from the user code to the Ruby implementation, and should be flag dependent. I.e. Ruby 2.0 introduced the EXTGLOB flag.

#7 [ruby-core:54271] Updated by Benoit Daloze about 3 years ago

rkh (Konstantin Haase) wrote:

  • Rubinius does not handle escaped [, { and }.
  • JRuby does not handle escaped [ and ]

These are implementation bugs, imo, and nothing to worry about here.

But it means the problem will not be solved in the general case before a while.
It must also have been problematic for some time, so I guess we are not in a hurry either.

If I am not mistaken, escaping is as simple as: dir.gsub(/[|]|*|\?|{|}/, '\\' + '\0').

Yes, but it shifts responsibility for keeping this up to date from the user code to the Ruby implementation,

I agree there should be Dir.escape or Dir.escape_glob.

and should be flag dependent. I.e. Ruby 2.0 introduced the EXTGLOB flag.

Can you give examples? If it works for every case except FNM_NOESCAPE, I think it is better to have a single simple way.

#8 [ruby-core:54273] Updated by Nobuyoshi Nakada about 3 years ago

(13/04/14 18:34), Eregon (Benoit Daloze) wrote:

I guess the most common use case is globbing on a directory recursively, so only the base directory is to be escaped, but this is not worth a specific method I think and could be done easily: Dir.glob("#{Dir.escape dir}/*/.rb") { |file| ... }

It reminded me about old proposal, Dir#glob (not Dir.glob).

--
Nobu Nakada

#9 [ruby-core:54280] Updated by Benoit Daloze about 3 years ago

nobu (Nobuyoshi Nakada) wrote:

It reminded me about old proposal, Dir#glob (not Dir.glob).

Interesting, do you have a link?

#10 [ruby-core:63352] Updated by Jack Nagel almost 2 years ago

An official API for escaping paths would be a hugely useful feature. In Homebrew, we use Dir[], Dir.glob and Pathname.glob a lot, but little attention has been paid to properly escaping paths, and over the years we have accumulated a great deal of potentially problematic code.

Benoit Daloze wrote:

Pathname could likely avoid this problem nicely in this situation: dir = Pathname("some_dir"); dir.glob("*/.rb") { |file| ... }

We also use Pathname quite heavily in Homebrew and would definitely take advantage of this.

Also available in: Atom PDF