Skip to main content

concat-all

A simple CLI tool to recursively concatenate all files of a certain extension in a directory into a single file.


Features

  • Concatenate all files with specified extension(s) in a directory tree
  • Supports multiple extensions at once (e.g., .py,.txt)
  • Optionally respects .gitignore rules, including negated patterns (e.g., !important_file.txt), to skip or include files and folders
  • Adds a comment header before each file's content in the output
  • Flexible output file naming and location
  • Dry-run mode to preview changes
  • Exclude specific files or directories using glob patterns
  • Limit directory recursion depth
  • Cross-platform and Python 3.9+ compatible

Installation

Clone the repository and install locally:

git clone https://github.com/mwmuni/concat-all.git
cd concat-all
python -m pip install .

Or use your preferred Python packaging tool.

uvx concat-all

Requirements

  • Python >= 3.9

Usage

Command Line Interface

concat-all <file_extensions> [options]

Arguments

Argument Description Example
<file_extensions> Comma-separated list of file extensions (without or with dot). Use * for all files. py,txt or *.md or *

Options

Option Description Default
--dir-path, -d Directory to search recursively. Current working directory
--output-file, -o Output file name (can include {file_extension} placeholder). dump_{file_extension}.txt
--output-file-dir, -D Directory to save the output file. Current working directory
--comment-prefix, -c Prefix for comment headers before each file's content. //
--gitignore, -i Respect .gitignore rules when selecting files. Disabled
--filename-suffix Suffix to append to the output file name. Supports {timestamp} and {unixtime} placeholders. Disabled
--dry-run, -n List files to be processed and the final output file path without writing any files. Disabled
--exclude <patterns> Comma-separated list of glob patterns to exclude files/directories (e.g., "*.log,temp/*"). Applied after .gitignore. None
--max-depth <depth> Maximum recursion depth. 0 for current directory, 1 for current + direct children, etc. -1 (unlimited)
--force Allow overwriting an existing output file. Disabled
--append Append to an existing output file (instead of overwriting). Disabled
--verbose Print files that are ignored/excluded/skipped. Disabled
--strict Fail on unreadable/binary files instead of skipping them. Disabled
--encoding <name> Encoding used to read input files. utf-8-sig
--errors <mode> Encoding error handler. strict
--max-bytes <n> Stop after writing at least N bytes to the output. -1 (unlimited)
--max-files <n> Stop after concatenating N files. -1 (unlimited)
--include-tree Append a list of included files to the output. Disabled

Examples

Concatenate all .py files in the current directory and subdirectories:

concat-all py

Concatenate .py and .txt files, saving output to a specific directory:

concat-all py,txt -D ./output_dir

Concatenate all files regardless of extension:

concat-all * -o all_files.txt

Concatenate .md files, respecting .gitignore:

concat-all md --gitignore

Change the comment prefix to #:

concat-all py -c "#"

Concatenate all .py files with a timestamp appended to the output file name:

concat-all py -o result.txt --filename_suffix "_{timestamp}"

Perform a dry run to see which .java files would be concatenated:

concat-all java --dry-run

Concatenate .ts files, excluding all files in node_modules and any *.test.ts files:

concat-all ts --exclude "node_modules/*,*.test.ts"

Concatenate .log files only from the current directory (no subdirectories):

concat-all log --max-depth 0

Concatenate .cfg files from the current directory and its direct children, respecting .gitignore:

concat-all cfg --max-depth 1 --gitignore

How it works

  • Recursively walks the specified directory up to --max-depth if provided.
  • Filters files by extension(s) or includes all files with *.
  • Optionally skips files/directories matching .gitignore patterns (supports negated patterns).
  • Skips files/directories matching user-provided --exclude glob patterns.
  • If not in --dry-run mode, concatenates file contents into a single output file.
  • Adds a comment header before each file's content indicating its path (in actual output).
  • In --dry-run mode, lists files that would be processed and the intended output file.

Programmatic Usage

You can also use concat-all as a Python module:

from concat_all import concat_files

concat_files(
    dir_path="path/to/dir",
    file_extensions="py,txt",
    output_file="./output/dump_{file_extension}.txt",
    comment_prefix="//",
    use_gitignore=True,
    force=False,
    append=False
)

Notes

  • The output file name supports the placeholder {file_extension} which will be replaced with the concatenated extensions or 'all' if using *.
  • The tool skips binary files or files it cannot read.
  • The output file itself is automatically excluded from concatenation.

License

MIT License


Author

Matthew Muller


Version

0.1.0


Enjoy! 😊

Metadata

Release files for concat-all 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for concat-all 0.3.0
File Size Uploaded
concat_all-0.3.0.tar.gz 13.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for concat-all 0.3.0
File Interpreter ABI Platform
concat_all-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 23.3 kB

Release files / concat_all-0.3.0.tar.gz

Download URL concat_all-0.3.0.tar.gz
Size 13.4 kB
Tags Source
SHA-256 checksum
How to use checksums
9f8696e29eb30b2e6042d8519332303d41b8eda8454b7b2e546bede830c0dc1b
BLAKE2b-256 checksum
How to use checksums
78e7dcca72b40608194c895decd6a44cce12e149b892dda8eac1fd597c39fdd5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Dec 12, 2025.

Transparency log

Release files / concat_all-0.3.0-py3-none-any.whl

Download URL concat_all-0.3.0-py3-none-any.whl
Size 9.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
46a19b7ad9510bcf5155a7871c8fdb60344c82366c08ee1438183166336d718b
BLAKE2b-256 checksum
How to use checksums
ad851d896cea3e70b1fef3600569f1fbd836c59405b9b4755f546033e35caf75
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Dec 12, 2025.

Transparency log

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page