Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsistent behavior with escaped single quotes & brace expansion #480

Open
Oasiris opened this issue Jan 5, 2025 · 3 comments · May be fixed by #481
Open

Inconsistent behavior with escaped single quotes & brace expansion #480

Oasiris opened this issue Jan 5, 2025 · 3 comments · May be fixed by #481
Milestone

Comments

@Oasiris
Copy link

Oasiris commented Jan 5, 2025

Environment

  • OS Version
    1. MacOS Ventura 13.4.1 (Apple Silicon)
    2. Windows 10
  • Node.js Version: 22.7.0
  • fast-glob: 3.3.2

Actual behavior

On MacOS and Windows, escaping single quotes will cause some globs that otherwise fail (return no results) to succeed, but cause other globs that would otherwise succeed to fail.

Expected behavior

  • Either the tests with escaped single quotes should return results, or the tests with unescaped single quotes should return results.

Steps to reproduce


Code sample

For this directory structure:

# Setup
mkdir fourth
touch "fourth/file'sA.md" 
touch "fourth/file'sB.md"
mkdir "fifth's"
touch "fifth's/fileA.md" 
touch "fifth's/fileB.md" 

The following test is picky about single quotes being escaped:

require("fast-glob").sync("fourth/file's{A,B}.md")
// => []
require("fast-glob").sync("fourth/file\\'s{A,B}.md")
// => ["fourth/file'sA.md", "fourth/file'sB.md"]

The following test is picky about single quotes being UN-escaped:

require("fast-glob").sync("fifth's/file*.md")
// => ["fifth's/fileA.md", "fifth's/fileB.md"]
require("fast-glob").sync("fifth\\'s/file*.md")
// => []

The following test fails regardless of whether the quote is escaped or not:

require("fast-glob").sync("fifth's/file{A,B}.md")
// => []
require("fast-glob").sync("fifth\\'s/file{A,B}.md")
// => []
@Oasiris
Copy link
Author

Oasiris commented Jan 5, 2025

In upstream dependencies [email protected] and [email protected], all tests with escaped single quotes pass:

// [email protected]
require('micromatch').match(["fourth/file'sA.md", "fourth/file'sB.md"], "fourth/file\\'s{A,B}.md")
// [ "fourth/file'sA.md", "fourth/file'sB.md" ]

require('micromatch').match(["fifth's/fileA.md", "fifth's/fileB.md"], "fifth\\'s/file*.md")
// [ "fifth's/fileA.md", "fifth's/fileB.md" ]

require('micromatch').match(["fifth's/fileA.md", "fifth's/fileB.md"], "fifth\\'s/file{A,B}.md")
// [ "fifth's/fileA.md", "fifth's/fileB.md" ]


// [email protected]
require('braces')("fourth/file\\'s{A,B}.md", { expand: true })
// [ "fourth/file'sA.md", "fourth/file'sB.md" ]

require('braces')("fifth\\'s/file{A,B}.md", { expand: true })
// [ "fifth's/fileA.md", "fifth's/fileB.md" ]

Reproduced test results on Windows 10.

@mrmlnc
Copy link
Owner

mrmlnc commented Jan 5, 2025

Thanks for the detailed description of the problem!

There are several problems here.


require("fast-glob").sync("fourth/file's{A,B}.md")
// => []
require("fast-glob").sync("fourth/file\\'s{A,B}.md")
// => ["fourth/file'sA.md", "fourth/file'sB.md"]

// Also

require("fast-glob").sync("fifth's/file{A,B}.md")
// => []
require("fast-glob").sync("fifth\\'s/file{A,B}.md")
// => []

This is happening because quotes may also be used as an alternative to backslashes for escaping. The braces package removes quotes by default.

The other solutions like wcmatch (python) and node-glob (js) do not follow this logic.


The following behavior is correct because the pattern is used without changes. The fifth's is a directory on file system.

require("fast-glob").sync("fifth's/file*.md")
// => ["fifth's/fileA.md", "fifth's/fileB.md"]

This behavior is incorrect, because the base directory for the pattern should be . (because the pattern has an escape symbol), and not fifth\\'s, as it is happening now. Ideally, escaping quotes for base directory should be removed at the pattern parsing stage.

require("fast-glob").sync("fifth\\'s/file*.md")
// => []

@mrmlnc
Copy link
Owner

mrmlnc commented Jan 7, 2025

There are two fixes here:

  1. ISSUE-56: correctly handle an unpaired quotes micromatch/braces#57
  2. ISSUE-480: remove backslashes from the pattern's base directory #481

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

Successfully merging a pull request may close this issue.

2 participants