Skip to main content
Glama
bin.mjs12.6 kB
#!/usr/bin/env node import { foregroundChild } from 'foreground-child'; import { existsSync } from 'fs'; import { jack } from 'jackspeak'; import { loadPackageJson } from 'package-json-from-dist'; import { basename, join } from 'path'; import { globStream } from './index.js'; const { version } = loadPackageJson(import.meta.url, '../package.json'); const j = jack({ usage: 'glob [options] [<pattern> [<pattern> ...]]', }) .description(` Glob v${version} Expand the positional glob expression arguments into any matching file system paths found. `) .opt({ cmd: { short: 'c', hint: 'command', description: `Run the command provided, passing the glob expression matches as arguments.`, }, }) .opt({ default: { short: 'p', hint: 'pattern', description: `If no positional arguments are provided, glob will use this pattern`, }, }) .flag({ shell: { default: false, description: `Interpret the command as a shell command by passing it to the shell, with all matched filesystem paths appended, **even if this cannot be done safely**. This is **not** unsafe (and usually unnecessary) when using the known Unix shells sh, bash, zsh, and fish, as these can all be executed in such a way as to pass positional arguments safely. **Note**: THIS IS UNSAFE IF THE FILE PATHS ARE UNTRUSTED, because a path like \`'some/path/\\$\\(cmd)'\` will be executed by the shell. If you do have positional arguments that you wish to pass to the command ahead of the glob pattern matches, use the \`--cmd-arg\`/\`-g\` option instead. The next major release of glob will fully remove the ability to use this option unsafely.`, }, }) .optList({ 'cmd-arg': { short: 'g', hint: 'arg', default: [], description: `Pass the provided values to the supplied command, ahead of the glob matches. For example, the command: glob -c echo -g"hello" -g"world" *.txt might output: hello world a.txt b.txt This is a safer (and future-proof) alternative than putting positional arguments in the \`-c\`/\`--cmd\` option.`, }, }) .flag({ all: { short: 'A', description: `By default, the glob cli command will not expand any arguments that are an exact match to a file on disk. This prevents double-expanding, in case the shell expands an argument whose filename is a glob expression. For example, if 'app/*.ts' would match 'app/[id].ts', then on Windows powershell or cmd.exe, 'glob app/*.ts' will expand to 'app/[id].ts', as expected. However, in posix shells such as bash or zsh, the shell will first expand 'app/*.ts' to a list of filenames. Then glob will look for a file matching 'app/[id].ts' (ie, 'app/i.ts' or 'app/d.ts'), which is unexpected. Setting '--all' prevents this behavior, causing glob to treat ALL patterns as glob expressions to be expanded, even if they are an exact match to a file on disk. When setting this option, be sure to enquote arguments so that the shell will not expand them prior to passing them to the glob command process. `, }, absolute: { short: 'a', description: 'Expand to absolute paths', }, 'dot-relative': { short: 'd', description: `Prepend './' on relative matches`, }, mark: { short: 'm', description: `Append a / on any directories matched`, }, posix: { short: 'x', description: `Always resolve to posix style paths, using '/' as the directory separator, even on Windows. Drive letter absolute matches on Windows will be expanded to their full resolved UNC paths, eg instead of 'C:\\foo\\bar', it will expand to '//?/C:/foo/bar'. `, }, follow: { short: 'f', description: `Follow symlinked directories when expanding '**'`, }, realpath: { short: 'R', description: `Call 'fs.realpath' on all of the results. In the case of an entry that cannot be resolved, the entry is omitted. This incurs a slight performance penalty, of course, because of the added system calls.`, }, stat: { short: 's', description: `Call 'fs.lstat' on all entries, whether required or not to determine if it's a valid match.`, }, 'match-base': { short: 'b', description: `Perform a basename-only match if the pattern does not contain any slash characters. That is, '*.js' would be treated as equivalent to '**/*.js', matching js files in all directories. `, }, dot: { description: `Allow patterns to match files/directories that start with '.', even if the pattern does not start with '.' `, }, nobrace: { description: 'Do not expand {...} patterns', }, nocase: { description: `Perform a case-insensitive match. This defaults to 'true' on macOS and Windows platforms, and false on all others. Note: 'nocase' should only be explicitly set when it is known that the filesystem's case sensitivity differs from the platform default. If set 'true' on case-insensitive file systems, then the walk may return more or less results than expected. `, }, nodir: { description: `Do not match directories, only files. Note: to *only* match directories, append a '/' at the end of the pattern. `, }, noext: { description: `Do not expand extglob patterns, such as '+(a|b)'`, }, noglobstar: { description: `Do not expand '**' against multiple path portions. Ie, treat it as a normal '*' instead.`, }, 'windows-path-no-escape': { description: `Use '\\' as a path separator *only*, and *never* as an escape character. If set, all '\\' characters are replaced with '/' in the pattern.`, }, }) .num({ 'max-depth': { short: 'D', description: `Maximum depth to traverse from the current working directory`, }, }) .opt({ cwd: { short: 'C', description: 'Current working directory to execute/match in', default: process.cwd(), }, root: { short: 'r', description: `A string path resolved against the 'cwd', which is used as the starting point for absolute patterns that start with '/' (but not drive letters or UNC paths on Windows). Note that this *doesn't* necessarily limit the walk to the 'root' directory, and doesn't affect the cwd starting point for non-absolute patterns. A pattern containing '..' will still be able to traverse out of the root directory, if it is not an actual root directory on the filesystem, and any non-absolute patterns will still be matched in the 'cwd'. To start absolute and non-absolute patterns in the same path, you can use '--root=' to set it to the empty string. However, be aware that on Windows systems, a pattern like 'x:/*' or '//host/share/*' will *always* start in the 'x:/' or '//host/share/' directory, regardless of the --root setting. `, }, platform: { description: `Defaults to the value of 'process.platform' if available, or 'linux' if not. Setting --platform=win32 on non-Windows systems may cause strange behavior!`, validOptions: [ 'aix', 'android', 'darwin', 'freebsd', 'haiku', 'linux', 'openbsd', 'sunos', 'win32', 'cygwin', 'netbsd', ], }, }) .optList({ ignore: { short: 'i', description: `Glob patterns to ignore`, }, }) .flag({ debug: { short: 'v', description: `Output a huge amount of noisy debug information about patterns as they are parsed and used to match files.`, }, version: { short: 'V', description: `Output the version (${version})`, }, help: { short: 'h', description: 'Show this usage information', }, }); try { const { positionals, values } = j.parse(); const { cmd, shell, all, default: def, version: showVersion, help, absolute, cwd, dot, 'dot-relative': dotRelative, follow, ignore, 'match-base': matchBase, 'max-depth': maxDepth, mark, nobrace, nocase, nodir, noext, noglobstar, platform, realpath, root, stat, debug, posix, 'cmd-arg': cmdArg, } = values; if (showVersion) { console.log(version); process.exit(0); } if (help) { console.log(j.usage()); process.exit(0); } //const { shell, help } = values if (positionals.length === 0 && !def) throw 'No patterns provided'; if (positionals.length === 0 && def) positionals.push(def); const patterns = all ? positionals : positionals.filter(p => !existsSync(p)); const matches = all ? [] : positionals.filter(p => existsSync(p)).map(p => join(p)); const stream = globStream(patterns, { absolute, cwd, dot, dotRelative, follow, ignore, mark, matchBase, maxDepth, nobrace, nocase, nodir, noext, noglobstar, platform: platform, realpath, root, stat, debug, posix, }); if (!cmd) { matches.forEach(m => console.log(m)); stream.on('data', f => console.log(f)); } else { cmdArg.push(...matches); stream.on('data', f => cmdArg.push(f)); // Attempt to support commands that contain spaces and otherwise require // shell interpretation, but do NOT shell-interpret the arguments, to avoid // injections via filenames. This affordance can only be done on known Unix // shells, unfortunately. // // 'bash', ['-c', cmd + ' "$@"', 'bash', ...matches] // 'zsh', ['-c', cmd + ' "$@"', 'zsh', ...matches] // 'fish', ['-c', cmd + ' "$argv"', ...matches] const { SHELL = 'unknown' } = process.env; const shellBase = basename(SHELL); const knownShells = ['sh', 'ksh', 'zsh', 'bash', 'fish']; if ((shell || /[ "']/.test(cmd)) && knownShells.includes(shellBase)) { const cmdWithArgs = `${cmd} "\$${shellBase === 'fish' ? 'argv' : '@'}"`; if (shellBase !== 'fish') { cmdArg.unshift(SHELL); } cmdArg.unshift('-c', cmdWithArgs); stream.on('end', () => foregroundChild(SHELL, cmdArg)); } else { if (shell) { process.emitWarning('The --shell option is unsafe, and will be removed. To pass ' + 'positional arguments to the subprocess, use -g/--cmd-arg instead.', 'DeprecationWarning', 'GLOB_SHELL'); } stream.on('end', () => foregroundChild(cmd, cmdArg, { shell })); } } } catch (e) { console.error(j.usage()); console.error(e instanceof Error ? e.message : String(e)); process.exit(1); } //# sourceMappingURL=bin.mjs.map

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/PancrePal-xiaoyibao/get-biji-dev-by-gemini3pro'

If you have feedback or need assistance with the MCP directory API, please join our Discord server