A simple CLI tool to recursively concatenate all files of a certain extension in a directory into a single file
Project description
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
.gitignorerules, 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-depthif provided. - Filters files by extension(s) or includes all files with
*. - Optionally skips files/directories matching
.gitignorepatterns (supports negated patterns). - Skips files/directories matching user-provided
--excludeglob patterns. - If not in
--dry-runmode, 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-runmode, 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! 😊
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file concat_all-0.3.0.tar.gz.
File metadata
- Download URL: concat_all-0.3.0.tar.gz
- Upload date:
- Size: 13.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9f8696e29eb30b2e6042d8519332303d41b8eda8454b7b2e546bede830c0dc1b
|
|
| MD5 |
95e327c6033e96b8a0150f3fe2d15d79
|
|
| BLAKE2b-256 |
78e7dcca72b40608194c895decd6a44cce12e149b892dda8eac1fd597c39fdd5
|
Provenance
The following attestation bundles were made for concat_all-0.3.0.tar.gz:
Publisher:
python-publish.yml on mwmuni/concat-all
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
concat_all-0.3.0.tar.gz -
Subject digest:
9f8696e29eb30b2e6042d8519332303d41b8eda8454b7b2e546bede830c0dc1b - Sigstore transparency entry: 760812030
- Sigstore integration time:
-
Permalink:
mwmuni/concat-all@228067d48f87752ce1350edbe24968d6522441bc -
Branch / Tag:
refs/tags/0.3.0 - Owner: https://github.com/mwmuni
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@228067d48f87752ce1350edbe24968d6522441bc -
Trigger Event:
release
-
Statement type:
File details
Details for the file concat_all-0.3.0-py3-none-any.whl.
File metadata
- Download URL: concat_all-0.3.0-py3-none-any.whl
- Upload date:
- Size: 9.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
46a19b7ad9510bcf5155a7871c8fdb60344c82366c08ee1438183166336d718b
|
|
| MD5 |
ac23896954b03c989a6a5652ced921e0
|
|
| BLAKE2b-256 |
ad851d896cea3e70b1fef3600569f1fbd836c59405b9b4755f546033e35caf75
|
Provenance
The following attestation bundles were made for concat_all-0.3.0-py3-none-any.whl:
Publisher:
python-publish.yml on mwmuni/concat-all
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
concat_all-0.3.0-py3-none-any.whl -
Subject digest:
46a19b7ad9510bcf5155a7871c8fdb60344c82366c08ee1438183166336d718b - Sigstore transparency entry: 760812031
- Sigstore integration time:
-
Permalink:
mwmuni/concat-all@228067d48f87752ce1350edbe24968d6522441bc -
Branch / Tag:
refs/tags/0.3.0 - Owner: https://github.com/mwmuni
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@228067d48f87752ce1350edbe24968d6522441bc -
Trigger Event:
release
-
Statement type: