Skip to content

Instantly share code, notes, and snippets.

@isaacs
Created November 18, 2014 23:04
Show Gist options
  • Select an option

  • Save isaacs/fc635c852c64ffabf2fd to your computer and use it in GitHub Desktop.

Select an option

Save isaacs/fc635c852c64ffabf2fd to your computer and use it in GitHub Desktop.

For the following directory structure containing files {a,b,c}/{d,e,f}/{x,y,z}.txt:

a
├── d/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
├── e/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
└── f/
    ├── x.txt
    ├── y.txt
    └── z.txt
b
├── d/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
├── e/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
└── f/
    ├── x.txt
    ├── y.txt
    └── z.txt
c
├── d/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
├── e/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
└── f/
    ├── x.txt
    ├── y.txt
    └── z.txt

What should the following negated globs return?

  1. !a
  2. !b/d
  3. !a/*
  4. !a/*/
  5. !a/d/*.txt
  6. !*a*/d/*.txt

Please post your answers in the comments here.

(Re: isaacs/node-glob#126 (comment))

@derekr

derekr commented Nov 18, 2014

Copy link
Copy Markdown
  1. [b/**/*, c/**/*]
  2. [a/**/*, b/e/*, b/f/*, c/**/*]
  3. [b/**/*, c/**/*]
  4. [b/**/*, c/**/*]
  5. [a/e/*, a/f/*, b/**/*, c/**/*]
  6. [a/e/*, a/f/*, b/**/*, c/**/*]

@aearly

aearly commented Nov 18, 2014

Copy link
Copy Markdown

I guess the question is whether !a/*/ should be treated as !(a/*/) or !(a)/*/. The former looks like what @derekr posted. The latter looks like:

  1. [b, d]
  2. [a/d, c/d]
  3. [b/*, c/*]
  4. [b/*/, c/*/]
  5. [b/d/*, c/d/*]
  6. [b/d/*, c/d/*]

@isaacs

isaacs commented Nov 19, 2014

Copy link
Copy Markdown
Author

@aearly What @derekr posted is that any negated pattern is essentially ** minus whatever matches the pattern matches.

@isaacs

isaacs commented Nov 19, 2014

Copy link
Copy Markdown
Author

@derekr Note that x/**/* is equivalent to x/**.

@isaacs

isaacs commented Nov 19, 2014

Copy link
Copy Markdown
Author

Oh, I guess not quite, since b/**/* will not match b itself. @derekr why doesn't !a/* match b?

@aearly

aearly commented Nov 19, 2014

Copy link
Copy Markdown

@isaacs You're right, I would interpret !(a/*/) as "the results of ** minus the results of a/*/".

@isaacs

isaacs commented Nov 19, 2014

Copy link
Copy Markdown
Author

@aerly Right. So, why doesn't !a/*/ match a? That isn't matched by a/*/, after all.

@dead-claudia

Copy link
Copy Markdown
  1. ['b/**', 'c/**']
  2. ['a/**', 'b/{e,f}/*']
  3. ['b/**', 'c/**']
    • It should be a shallow exclusion: if there was any grandchildren directories (e.g. `a/d/g/'), they should be included.
  4. ['b/**', 'c/**']
    • Same reasoning as above.
  5. ['a/{e,f}/**', 'b/**', 'c/**']
    • Also include anything not .txt in a/d/.
  6. ['a/{e,f}/**', 'b/**', 'c/**']
    • Same reasoning as above.

I do think your example case is a little limited in what it can allow, given all three folders are the same format, all the files of one expension, and the structure two levels deep, excluding files (3 would allow for better enumeration of special cases). Just my opinion. Maybe something along the lines of this could work better?

|-- a/
|    |-- d/
|    |     |-- g/
|    |     |     |-- h.txt
|    |     |-- x.txt
|    |     |-- y.dat
|    |     |-- z.txt
|    |-- e/
|    |     |-- g/
|    |     |     |-- h.js
|    |     |-- x.txt
|    |     |-- y.js
|    |     |-- z.txt
|    |-- f/
|          |-- g/
|          |     |-- h.txt
|          |-- x.txt
|          |-- y.dat
|          |-- z.txt
|-- b/
|    |-- d/
|    |    |-- g/
|    |    |     |-- h.txt
|    |    |-- x.txt
|    |    |-- y.js
|    |    |-- z.txt
|    |-- e/
|    |    |-- g/
|    |    |     |-- h.js
|    |    |-- x.txt
|    |    |-- y.js
|    |    |-- z.txt
|    |-- f/
|        |-- g/
|        |     |-- h.txt
|        |-- x.txt
|        |-- y.js
|        |-- z.txt
|-- a/
     |-- d/
     |    |-- g/
     |    |     |-- h.txt
     |    |-- x.txt
     |    |-- y.js
     |    |-- z.txt
     |-- e/
     |    |-- g/
     |    |     |-- h.js
     |    |-- x.txt
     |    |-- y.js
     |    |-- z.txt
     |-- f/
          |-- g/
          |     |-- h.txt
          |-- x.txt
          |-- y.js
          |-- z.txt

What would you all think should be matched with these?

  1. !*/e/**/*.js
  2. `!a/*/.js
  3. !a/*/*.js
  4. !b/*
  5. !b/*/

@isaacs

isaacs commented Nov 19, 2014

Copy link
Copy Markdown
Author

@IMPinball @aerly @derekr Maybe can you list out what you think the actual result array should be, rather than translating it into other globs?

@derekr

derekr commented Nov 19, 2014

Copy link
Copy Markdown

Sorry wasn't getting any notifications!

  1. !a
b
├── d/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
├── e/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
└── f/
    ├── x.txt
    ├── y.txt
    └── z.txt
c
├── d/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
├── e/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
└── f/
    ├── x.txt
    ├── y.txt
    └── z.txt
  1. !b/d
a
├── d/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
├── e/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
└── f/
    ├── x.txt
    ├── y.txt
    └── z.txt
b
├── e/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
└── f/
    ├── x.txt
    ├── y.txt
    └── z.txt
c
├── d/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
├── e/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
└── f/
    ├── x.txt
    ├── y.txt
    └── z.txt
  1. !a/*

As it works in .gitignore I imagine this matches the directory as well as contents, but I can
also see how it might include the directory, but negate it's contents.

b
├── d/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
├── e/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
└── f/
    ├── x.txt
    ├── y.txt
    └── z.txt
c
├── d/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
├── e/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
└── f/
    ├── x.txt
    ├── y.txt
    └── z.txt
  1. !a/*/
b
├── d/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
├── e/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
└── f/
    ├── x.txt
    ├── y.txt
    └── z.txt
c
├── d/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
├── e/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
└── f/
    ├── x.txt
    ├── y.txt
    └── z.txt
  1. !a/d/*.txt
a
├── e/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
└── f/
    ├── x.txt
    ├── y.txt
    └── z.txt
b
├── d/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
├── e/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
└── f/
    ├── x.txt
    ├── y.txt
    └── z.txt
c
├── d/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
├── e/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
└── f/
    ├── x.txt
    ├── y.txt
    └── z.txt
  1. !*a*/d/*.txt
a
├── e/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
└── f/
    ├── x.txt
    ├── y.txt
    └── z.txt
b
├── d/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
├── e/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
└── f/
    ├── x.txt
    ├── y.txt
    └── z.txt
c
├── d/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
├── e/
│   ├── x.txt
│   ├── y.txt
│   └── z.txt
└── f/
    ├── x.txt
    ├── y.txt
    └── z.txt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment