minimatch の使い方 — JavaScriptでglob パターンマッチングを行うライブラリ
一言でいうと
minimatch は、glob パターン(*.js や src/**/*.ts など)を JavaScript の正規表現に変換し、文字列のパターンマッチングを行うライブラリです。npm 内部でも使われている、Node.js エコシステムにおけるglob マッチングの定番パッケージです。
どんな時に使う?
- ファイルパスのフィルタリング — ファイル一覧から特定の拡張子やディレクトリ配下のファイルだけを抽出したいとき
- 独自のビルドツール・CLIツールの開発 —
.gitignoreのようなパターン指定による除外・包含ロジックを実装したいとき - 設定ファイルのパターンマッチ — ユーザーが指定した glob パターンに対して、対象パスが一致するかどうかを判定したいとき
インストール
# npm
npm install minimatch
# yarn
yarn add minimatch
# pnpm
pnpm add minimatch
基本的な使い方
最もシンプルなパターンは、minimatch(path, pattern) で文字列がglobパターンに一致するかを判定する使い方です。
import { minimatch } from 'minimatch';
// 拡張子マッチ
console.log(minimatch('bar.foo', '*.foo')); // true
console.log(minimatch('bar.foo', '*.bar')); // false
// ディレクトリを含むパスのマッチ
console.log(minimatch('src/components/Button.tsx', 'src/**/*.tsx')); // true
console.log(minimatch('test/utils.ts', 'src/**/*.ts')); // false
// ブレース展開
console.log(minimatch('index.ts', '*.{ts,tsx}')); // true
console.log(minimatch('index.css', '*.{ts,tsx}')); // false
// 否定パターン
console.log(minimatch('README.md', '!*.md')); // false(否定なので .md は不一致扱い)
よく使うAPI — minimatch の主要メソッド解説
1. minimatch(path, pattern, options?)
メインのエクスポート関数です。パスがパターンに一致するかを boolean で返します。
import { minimatch } from 'minimatch';
// matchBase: true にすると、パスのベースネーム部分だけでマッチ判定する
const isJS = minimatch('path/to/file.js', '*.js', { matchBase: true });
console.log(isJS); // true
// nocase: true で大文字小文字を無視
console.log(minimatch('FILE.TXT', '*.txt', { nocase: true })); // true
2. minimatch.filter(pattern, options?)
Array.prototype.filter に渡せるフィルタ関数を返します。ファイル一覧の絞り込みに便利です。
import { minimatch } from 'minimatch';
const fileList = [
'app.ts',
'app.test.ts',
'utils.js',
'README.md',
'styles.css',
];
// TypeScript ファイルだけ抽出
const tsFiles = fileList.filter(minimatch.filter('*.ts', { matchBase: true }));
console.log(tsFiles); // ['app.ts', 'app.test.ts']
3. new Minimatch(pattern, options?) — Minimatch クラス
同じパターンで繰り返しマッチ判定する場合、Minimatch クラスを使うとパターンのパース結果を再利用でき、パフォーマンスが向上します。
import { Minimatch } from 'minimatch';
const mm = new Minimatch('src/**/*.{ts,tsx}', { dot: false });
const paths = [
'src/index.ts',
'src/components/Button.tsx',
'src/.hidden/secret.ts',
'dist/bundle.js',
];
const matched = paths.filter(p => mm.match(p));
console.log(matched);
// ['src/index.ts', 'src/components/Button.tsx']
// (.hidden 配下は dot: false のためマッチしない)
便利なプロパティ・メソッド
const mm = new Minimatch('**/*.test.ts');
// パターンを正規表現に変換
const re = mm.makeRe();
console.log(re); // /^(?:(?!...)...)$/ のような RegExp オブジェクト
// パターンにワイルドカード等のマジック文字が含まれるか
console.log(mm.hasMagic()); // true
// 否定パターンかどうか
const neg = new Minimatch('!*.log');
console.log(neg.negate); // true
4. minimatch.escape(pattern, options?)
glob のマジック文字(*, ?, [ など)をエスケープし、リテラル文字列としてのみマッチするパターンに変換します。
import { minimatch } from 'minimatch';
// ユーザー入力をリテラルとして安全に扱いたい場合
const userInput = 'file[1].txt';
const escaped = minimatch.escape(userInput);
console.log(escaped); // 'file\\[1\\].txt'
console.log(minimatch('file[1].txt', escaped)); // true
console.log(minimatch('fileX.txt', escaped)); // false
5. minimatch.unescape(pattern, options?)
escape の逆操作です。エスケープされたパターンから元の文字列を復元します。
import { minimatch } from 'minimatch';
const escaped = minimatch.escape('hello*.txt');
console.log(escaped); // 'hello\\*.txt'
console.log(minimatch.unescape(escaped)); // 'hello*.txt'
主要オプション一覧
| オプション | 型 | デフォルト | 説明 |
|---|---|---|---|
dot | boolean | false | true にすると . で始まるファイル名にもマッチ |
nocase | boolean | false | 大文字小文字を区別しない |
matchBase | boolean | false | パターンにスラッシュがなければベースネームのみでマッチ |
noglobstar | boolean | false | ** をグロブスターとして扱わない |
debug | boolean | false | デバッグ出力を有効化 |
windowsPathsNoEscape | boolean | false | \ をエスケープではなくパス区切りとして扱う |
類似パッケージとの比較
| パッケージ | 特徴 | ダウンロード数 | 備考 |
|---|---|---|---|
| minimatch | npm 内部で使用。標準的な glob マッチャー | 非常に多い | 本記事の対象 |
| micromatch | 高速・多機能。拡張 glob 構文が豊富 | 多い | minimatch より高速とされる |
| picomatch | micromatch の内部エンジン。軽量 | 多い | 依存ゼロで最小限の API |
| glob | ファイルシステムを実際に走査する | 多い | minimatch を内部で使用 |
| multimatch | 複数パターンの AND/OR マッチ | 中程度 | minimatch ベース |
選定の目安:
- ファイルシステムの走査が不要で、文字列のパターンマッチだけなら → minimatch または micromatch
- パフォーマンスが最優先なら → picomatch / micromatch
- npm エコシステムとの互換性・安定性を重視するなら → minimatch
注意点・Tips
⚠️ セキュリティ:ユーザー入力をパターンに使わない
minimatch は内部で正規表現を生成するため、信頼できない入力をパターンとして渡すと ReDoS(正規表現によるサービス拒否) 攻撃のリスクがあります。ユーザー入力をパターンに使う場合は、必ず minimatch.escape() でエスケープするか、そもそもパターンとして使わない設計にしてください。
// ❌ 危険:ユーザー入力をそのままパターンに渡す
minimatch(filePath, userInput);
// ✅ 安全:エスケープしてリテラルマッチにする
minimatch(filePath, minimatch.escape(userInput));
Windows でのパス区切り
glob パターンには 常にスラッシュ (/) を使用 してください。バックスラッシュ (\) はエスケープ文字として解釈されます。パス引数側では \ も / も受け付けますが、パターン側は / のみです。
// ❌ パターンにバックスラッシュを使わない
minimatch('src\\index.ts', 'src\\*.ts');
// ✅ パターンはスラッシュで統一
minimatch('src\\index.ts', 'src/*.ts'); // Windows でも true
Minimatch クラスの再利用でパフォーマンス改善
ループ内で同じパターンを何度もマッチさせる場合、毎回 minimatch() を呼ぶとパターンのパースが繰り返されます。Minimatch クラスをループ外で生成しておきましょう。
import { Minimatch } from 'minimatch';
// ✅ パース結果を再利用
const mm = new Minimatch('**/*.test.ts');
const testFiles = thousandsOfFiles.filter(f => mm.match(f));
dot オプションの落とし穴
デフォルトでは .gitignore や .env のようなドットファイルにはマッチしません。意図的にドットファイルも対象にしたい場合は { dot: true } を指定してください。
console.log(minimatch('.env', '*')); // false
console.log(minimatch('.env', '*', { dot: true })); // true
まとめ
minimatch は、glob パターンによる文字列マッチングを JavaScript で実現するための堅実なライブラリです。npm 自体が内部で使用しており、エコシステムとの互換性・信頼性は折り紙付きです。ユーザー入力をパターンに渡さないというセキュリティ上の注意点さえ守れば、ファイルパスのフィルタリングやビルドツール開発など、幅広い場面で安心して活用できます。