File concatenation with glob patterns guide
Concatenates files matching glob patterns into a single output with separators. Use when creating LLM context files, merging documentation, or bundling source code for review.
/plugin marketplace add dnvriend/concat-glob-tool/plugin install concat-glob-tool@concat-glob-toolThis skill inherits all available tools. When active, it can use any tool Claude has access to.
Master file concatenation with glob patterns for efficient file merging, documentation bundling, and LLM context generation. This skill covers CLI usage, library integration, and advanced patterns.
Use this skill when:
Do NOT use this skill for:
cat or cp)A production-ready CLI utility that concatenates files matching glob patterns with intelligent separators. Features dry-run mode, stdin support, and both CLI and library modes.
# From source
git clone https://github.com/dnvriend/concat-glob-tool.git
cd concat-glob-tool
uv tool install .
# Verify
concat-glob-tool --version
# Preview (dry-run, default)
concat-glob-tool '*.py' -o output.txt
# Execute
concat-glob-tool '*.py' '*.md' -o output.txt --no-dry-run
# Stdin mode
find . -name '*.py' | concat-glob-tool --stdin -o output.txt --no-dry-run
Concatenate files matching glob patterns to a single output file with intelligent separators.
Usage:
concat-glob-tool PATTERNS... --output-file FILE [OPTIONS]
Arguments:
PATTERNS...: One or more glob patterns (e.g., *.py, src/**/*.md)-o, --output-file FILE: Output file path (required)--separator TEXT: Separator text between files (default: ---)-n, --dry-run: Preview without writing (enabled by default)--no-dry-run: Actually execute the concatenation-f, --force: Overwrite existing output file-v, --verbose: Enable verbose output (repeatable: -v, -vv, -vvv)--version: Show version--help: Show help message with examplesExamples:
# Basic concatenation - preview mode (dry-run)
concat-glob-tool '*.py' -o output.txt
# Execute concatenation
concat-glob-tool '*.py' -o output.txt --no-dry-run
# Multiple patterns
concat-glob-tool '*.py' '*.md' '*.txt' -o combined.txt --no-dry-run
# Recursive patterns
concat-glob-tool 'src/**/*.py' -o all-code.txt --no-dry-run
# Multiple recursive patterns
concat-glob-tool 'src/**/*.py' 'tests/**/*.py' -o codebase.txt --no-dry-run
# Custom separator
concat-glob-tool '*.py' -o output.txt --separator '===' --no-dry-run
# Force overwrite existing file
concat-glob-tool '*.py' -o existing.txt --force --no-dry-run
# Verbose output
concat-glob-tool '*.py' -o output.txt -vv --no-dry-run
# LLM context generation
concat-glob-tool 'src/**/*.py' 'tests/**/*.py' '*.md' \
-o llm-context.txt \
--separator '---' \
--no-dry-run
Output Format: Files are concatenated with this separator format between each file:
---
# /path/to/file.py
---
[file contents]
The separator includes:
---)Dry-Run Mode (Default): By default, the tool runs in preview mode showing:
--no-dry-run to executeThis prevents accidental overwrites and lets you verify operations first.
Read file paths from stdin and concatenate them. Useful for integration with find, fd, grep, and other tools.
Usage:
find ... | concat-glob-tool --stdin --output-file FILE [OPTIONS]
Arguments:
-s, --stdin: Read file paths from stdin (one per line)-o, --output-file FILE: Output file path (required)--separator TEXT: Separator text (default: ---)--no-dry-run: Execute the concatenation-f, --force: Overwrite existing output file-v, --verbose: Verbose outputExamples:
# From find command
find . -name '*.py' -type f | concat-glob-tool --stdin -o output.txt --no-dry-run
# From fd (faster find alternative)
fd -e py | concat-glob-tool --stdin -o output.txt --no-dry-run
# Filter with grep
find . -name '*.py' | grep -v test | concat-glob-tool --stdin -o output.txt --no-dry-run
# Complex pipeline
find . -name '*.py' -type f | \
grep -v __pycache__ | \
grep -v .venv | \
concat-glob-tool --stdin -o filtered.txt --no-dry-run
# With custom separator
find . -name '*.md' | concat-glob-tool --stdin -o docs.txt --separator '===' --no-dry-run
Note:
--stdin and glob patterns in the same commandGlob patterns support environment variable expansion and home directory shortcuts.
Examples:
# Home directory expansion
concat-glob-tool '~/projects/*.py' -o output.txt --no-dry-run
# Environment variables
concat-glob-tool '$HOME/src/**/*.py' -o output.txt --no-dry-run
# Mixed
concat-glob-tool '~/.config/*.conf' '$PROJECT_DIR/**/*.md' -o output.txt --no-dry-run
Use concat-glob-tool as a Python library for programmatic integration.
Installation:
pip install concat-glob-tool
# or
uv add concat-glob-tool
Core API:
from concat_glob_tool import (
expand_glob_patterns,
concatenate_files,
format_separator,
ConcatError,
NoMatchesError,
OutputExistsError,
)
from pathlib import Path
# Expand glob patterns
files = expand_glob_patterns(["*.py", "src/**/*.md"])
print(f"Found {len(files)} files")
# Concatenate files
result = concatenate_files(
files=files,
output_file=Path("output.txt"),
separator="---",
force=False,
dry_run=False,
)
print(f"Concatenated {result['files_count']} files")
print(f"Wrote {result['bytes_written']} bytes to {result['output_file']}")
Exception Handling:
from pathlib import Path
from concat_glob_tool import (
concatenate_files,
expand_glob_patterns,
NoMatchesError,
OutputExistsError,
ConcatError,
)
try:
files = expand_glob_patterns(["*.py"])
result = concatenate_files(
files=files,
output_file=Path("output.txt"),
force=False,
dry_run=False,
)
print(f"Success: {result}")
except NoMatchesError as e:
print(f"No files found: {e}")
except OutputExistsError as e:
print(f"Output exists: {e}")
except ConcatError as e:
print(f"Error: {e}")
Integration Example:
#!/usr/bin/env python3
"""Example: Concatenate Python files with custom logic."""
from pathlib import Path
from concat_glob_tool import expand_glob_patterns, concatenate_files
def main():
# Find all Python files
files = expand_glob_patterns(["src/**/*.py", "tests/**/*.py"])
# Filter files (e.g., exclude __init__.py)
filtered_files = [f for f in files if f.name != "__init__.py"]
# Concatenate
result = concatenate_files(
files=filtered_files,
output_file=Path("codebase.txt"),
separator="===",
force=True,
dry_run=False,
)
print(f"✅ Concatenated {result['files_count']} files")
print(f"📝 Output: {result['output_file']}")
print(f"💾 Size: {result['bytes_written']} bytes")
if __name__ == "__main__":
main()
Customize the separator text while maintaining the format structure.
Examples:
# Simple separator
concat-glob-tool '*.py' -o output.txt --separator '---' --no-dry-run
# Equals signs
concat-glob-tool '*.py' -o output.txt --separator '===' --no-dry-run
# Hash separator
concat-glob-tool '*.py' -o output.txt --separator '###' --no-dry-run
# Custom text
concat-glob-tool '*.py' -o output.txt --separator 'FILE' --no-dry-run
Separator Format:
The separator structure is always: \n{separator}\n# {filename}\n{separator}\n
Example with --separator '===':
===
# /path/to/file.py
===
[file contents]
</details>
<details>
<summary><strong>🔧 Troubleshooting (Click to expand)</strong></summary>
Issue: No files matched the patterns
$ concat-glob-tool '*.nonexistent' -o out.txt --no-dry-run
Error: No files matched the patterns: *.nonexistent
Solution: Verify glob patterns are correct. Examples:
- '*.py' for Python files in current directory
- '**/*.py' for Python files recursively
- 'src/**/*.{py,md}' for multiple extensions
Solution:
--verbose to see detailed loggingls first: ls *.pyIssue: Output file already exists
$ concat-glob-tool '*.py' -o existing.txt --no-dry-run
Error: Output file already exists: existing.txt
Solution: Use --force to overwrite or choose a different output file.
Solution:
--force flag to overwrite: concat-glob-tool '*.py' -o existing.txt --force --no-dry-runIssue: Cannot use both --stdin and glob patterns
$ concat-glob-tool '*.py' --stdin -o out.txt
Error: Cannot use both --stdin and glob patterns.
Solution: Use either --stdin OR provide glob patterns, not both.
Solution:
concat-glob-tool '*.py' -o out.txt --no-dry-runfind . -name '*.py' | concat-glob-tool --stdin -o out.txt --no-dry-runIssue: Forgot --no-dry-run flag
$ concat-glob-tool '*.py' -o output.txt
[DRY-RUN] Would concatenate 10 files to: output.txt
...
To execute, add --no-dry-run flag.
Solution:
--no-dry-run to actually execute# Full help with examples
concat-glob-tool --help
# Version information
concat-glob-tool --version
# Verbose output for debugging
concat-glob-tool '*.py' -o output.txt -vv --no-dry-run
-v: INFO level (operations and progress)-vv: DEBUG level (detailed information)-vvv: TRACE level (library internals)All logs go to stderr, keeping stdout clean for piping.
</details>0: Success1: Error (NoMatchesError, OutputExistsError, ConcatError, validation errors)Separator Format:
\n---\n# /path/to/filename\n---\n
Components:
--separator)Dry-Run Output:
Execution Output:
Successfully concatenated 10 files to output.txt (52482 bytes)
Always Preview First: Use default dry-run mode to verify operations before executing with --no-dry-run
Use Descriptive Output Names: Name output files clearly indicating contents (e.g., llm-context.txt, all-python-code.txt)
Leverage Verbose Mode: Use -v or -vv when troubleshooting or learning the tool's behavior
Quote Glob Patterns: Always quote patterns in shell to prevent premature expansion: '*.py' not *.py
Test Patterns with ls: Verify glob patterns work with ls before using in concat-glob-tool
Use stdin for Complex Filtering: Combine with find, fd, grep for advanced file selection
Custom Separators for Context: Use meaningful separators when creating context files for specific purposes