Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

481
Views
Is there a way to write a glob pattern that matches all files except those in a folder?

I need to write a file glob that will match all files except for those that are contained within a certain folder (e.g. all files except those contained within the high level folder foo/.

I've arrived at the following glob:

!(foo)/**/*

However, this glob doesn't seem to match on any files in Ruby's File.fnmatch (even with FNM_PATHNAME and FNM_DOTMATCH set to true.

Also, Ruby's glob interpreter seemed to have different behavior than JavaScript's:

JavaScript glob interpreter matches all strings

Ruby glob interpreter doesn't match any strings:

2.6.2 :027 > File.fnmatch("!(foo)/**/*", "hello/world.js")
 => false
2.6.2 :028 > File.fnmatch("!(foo)/**/*", "test/some/globs")
 => false
2.6.2 :029 > File.fnmatch("!(foo)/**/*", "foo/bar/something.txt")
 => false
over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

If you really need to use a glob then you can list what is allowed, making it equivalent to the negation:

extglob = "{[^f]*,f,f[^o]*,fo,fo[^o]*,foo?*}/**/*"

File.fnmatch(extglob, "hello/world.js", File::FNM_EXTGLOB | File::FNM_PATHNAME)
#=> true

File.fnmatch(extglob, "test/some/globs", File::FNM_EXTGLOB | File::FNM_PATHNAME)
#=> true

File.fnmatch(extglob, "foo/bar/something.txt", File::FNM_EXTGLOB | File::FNM_PATHNAME)
#=> false

File.fnmatch(extglob, "food/bar/something.txt", File::FNM_EXTGLOB | File::FNM_PATHNAME)
#=> true

{[^f]*,f,f[^o]*,fo,fo[^o]*,foo?*} means:

  • Any string that doesn't start with f
  • The strinf f
  • Any string that starts with f and whose second character is not a o
  • The string fo
  • Any string that starts with fo and whose third character is not a o
  • Any string that starts with foo if it has at least one more character

Update

If your string literal is too long it could become a pain to generate a glob that negates it, so why not make a function for it?

def extglob_neg str
  str.each_char.with_index.with_object([]) do |(_,i),arr|
    arr << "#{str[0,i]}[^#{str[i]}]*"
    arr << str[0..i]
  end.join(',').prepend('{').concat('?*}')
end

extglob_neg "Food"
#=> "{[^F]*,F,F[^o]*,Fo,Fo[^o]*,Foo,Foo[^d]*,Food?*}"

note: I didn't implement any glob escaping in this function because it seemed a little complicated. I may be wrong though

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!