5

This is quite an easy one for you guys, but I can't find a definitive/formal answer to this question.

Suppose we are in directory A. Then,

"A/* " probably means: Every file and folder directly inside A.

"A/** " then may mean: Every file and folder inside A, and every file and folder directly inside every child that is directly inside A. (Basically, an extension of /* operator that traverses one level deeper of the root folder? aka "/** " = "/* /* " )

My "directly inside" terminology might be wrong. May be its better to say "direct child" or something, but you get the idea.

Then, what does "A/**/* " mean? Is it equal to "A/* /* /* " ?

Although this seems basic, its quite confusing when I don't have a formal definition of the operators.

I'm currently using Javascript and trying to modify a Gruntfile. But I guess these operators may come up in any context.

user2864740
  • 60,010
  • 15
  • 145
  • 220
batilc
  • 691
  • 1
  • 5
  • 16

2 Answers2

10

This behavior is not intrinsic to JavaScript and is not related to any operators: as far as JavaScript is concerned, it is just a string.

The handling of such glob expansion is determined by the specific library/consumer. For gruntjs it is covered in Grunt Globbing Patterns:

It is often impractical to specify all source filepaths individually, so Grunt supports filename expansion (also know as globbing) via the built-in node-glob and minimatch libraries ..

  • * matches any number of characters, but not /

  • ** matches any number of characters, including /, as long as it's the only thing in a path part

All most people need to know is that foo/*.js will match all files ending with .js in the foo/ subdirectory, but foo/**/*.js will match all files ending with .js in the foo/ subdirectory and all of its subdirectories.

As such (but refer to the specific documentation!), /**/ generally means "match any depth of directories" and /*/ or /* means "match a single directory or file part".


The gruntjs documentation is a bit vague on the specific mechanics of ** in the standard "/**/*.x" pattern, but referring to node-glob says:

If a "globstar" (**) is alone in a path portion, then it matches zero or more directories and subdirectories searching for matches. It does not crawl symlinked directories.

[.. The double-star character] is supported in the manner of bsdglob and bash 4.3, where ** only has special significance if it is the only thing in a path part. That is, a/**/b will match a/x/y/b, but a/**b will not.

Using this knowledge we get the equivalency (when used as a path component), of A/**/f with A/f, A/*/f, A/*/*/f, etc for every number of intermediate directories.

Community
  • 1
  • 1
user2864740
  • 60,010
  • 15
  • 145
  • 220
  • Oh I see better now, thanks. But I don't get this: why do I need A/**/* instead of A/** ? The way I see it, A/** can mean any file inside A and inside its subdirectories ? – batilc Dec 19 '14 at 22:22
  • @batilc Updated the answer for the specific case. – user2864740 Dec 19 '14 at 22:31
  • Thank you for the help. I need one more specific clarification about this, because I think I understand the explanation you provide, but it is inconsistent with what I have in my hand. I'm pretty new in grunt, so I may be wrong with my assumption: I have this line: ......files: [{ expand: true, cwd: 'src/', src: ['img/**'], dest: 'www/' }]..... So what I was expecting that Its going to copy any file under img. However, if it is not matching any files, what does it do then? Return only the sub-folders and leave the file-search to grunt inside those sub-folders? – batilc Dec 19 '14 at 22:38
  • Use `"img/**/*"` to copy every file recursively. Without the trailing `/*` the globstar is *not* in a "path component" and thus does not expand to subdirectories as desired. – user2864740 Dec 19 '14 at 22:39
  • Actually that line does copy every folder and file under "img" to "www". So my guess is that grunt only wants the folders-list to be copied, not the files itself. – batilc Dec 19 '14 at 22:46
  • @batilc Both approaches "should" work (but I'm not on node right now, so I can't test it and could be wrong). I would use the specific directory `"img"`, and let normal copy recursion work, if does accomplish the desired goal. – user2864740 Dec 19 '14 at 22:47
1

If you see A/**/* that means to recursively search all the way down the tree of every folder under folder A. For more information look up basic linux style file commands.

Chris Franklin
  • 3,864
  • 2
  • 16
  • 19
  • A/**/*.js then means that every js file inside every sub-folder of A, including the A folder itself? Btw cant still find a legitimate documentation of this :/ – batilc Dec 19 '14 at 22:19
  • yes, `**/*.js` will match any `.js` file under the directory. The `*` is a wildcard matcher for file manipulation. `**` is a special wildcard that means `every directory starting here` so it won't match file names. – Chris Franklin Dec 19 '14 at 22:27