有没有办法编写一个 glob 模式来匹配除文件夹中的文件之外的所有文件?
Is there a way to write a glob pattern that matches all files except those in a folder?
我需要编写一个文件 glob 来匹配除特定文件夹中包含的文件之外的所有文件(例如,除高级文件夹 foo/
.
中包含的文件之外的所有文件)
我到达了以下 glob:
!(foo)/**/*
但是,此 glob 似乎与 Ruby 的 File.fnmatch
中的任何文件都不匹配(即使 FNM_PATHNAME
和 FNM_DOTMATCH
设置为 true
.
此外,Ruby 的 glob 解释器的行为似乎与 JavaScript 的不同:
JavaScript glob interpreter 匹配所有字符串
Ruby glob 解释器不匹配任何字符串:
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
如果你真的需要使用 glob 那么你可以列出允许的内容,使其等同于否定:
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?*}
表示:
- 任何不以
f
开头的字符串
- strinf
f
- 任何以
f
开头且第二个字符为 not a o
的字符串
- 字符串
fo
- 任何以
fo
开头且第三个字符为 not a o
的字符串
- 任何以
foo
开头的字符串,如果它至少还有一个字符
更新
如果你的字符串文字太长,生成一个否定它的 glob 可能会很痛苦,那么为什么不为它创建一个函数呢?
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?*}"
注意:我没有在这个函数中实现任何glob转义,因为它看起来有点复杂。不过我可能错了
我需要编写一个文件 glob 来匹配除特定文件夹中包含的文件之外的所有文件(例如,除高级文件夹 foo/
.
我到达了以下 glob:
!(foo)/**/*
但是,此 glob 似乎与 Ruby 的 File.fnmatch
中的任何文件都不匹配(即使 FNM_PATHNAME
和 FNM_DOTMATCH
设置为 true
.
此外,Ruby 的 glob 解释器的行为似乎与 JavaScript 的不同:
JavaScript glob interpreter 匹配所有字符串
Ruby glob 解释器不匹配任何字符串:
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
如果你真的需要使用 glob 那么你可以列出允许的内容,使其等同于否定:
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?*}
表示:
- 任何不以
f
开头的字符串
- strinf
f
- 任何以
f
开头且第二个字符为 not ao
的字符串
- 字符串
fo
- 任何以
fo
开头且第三个字符为 not ao
的字符串
- 任何以
foo
开头的字符串,如果它至少还有一个字符
更新
如果你的字符串文字太长,生成一个否定它的 glob 可能会很痛苦,那么为什么不为它创建一个函数呢?
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?*}"
注意:我没有在这个函数中实现任何glob转义,因为它看起来有点复杂。不过我可能错了