Combines several files into one, traversing folders as needed and adding optional headers and footers.
This can be useful in many scenarios, for example:
- Generate a single (or a handful of) SQL script from sources for easier deployment.
- Combine Markdown files located throughout a repo.
- Make one file containing all your style sheets.
- You get the idea.
With npm installed, run
$ npm install combine-files
combine-files --mask=*.txt
- Recursively combines all *.txt files in the current folder and stores the result in output.txt
combine-files --mask=*.sql --input=./scripts --output=./combined-script.sql
- Recursively combines all *.sql files in the ./scripts folder and stores the result in ./combined-script.sql
combine-files --config=./sample-config.json
- Recursively combines files according to the configuration found in ./sample-config.json
combine-files
- Recursively combines files according to the configuration found in ./combinefiles.json
Configuration files are a simple JSON structure, for example:
{
"fileGroups": [{
"groupName": "Change logs",
"fileGlobs": ["**/changes.md"],
"tocEntry": " TOC Entry goes here"
}, {
"groupName": "Readme files",
"fileGlobs": ["**/readme.md"],
"tocEntry": " TOC Entry goes here"
}]
}
The full definition of a file group is shown in the section: IConfigFileGroup interface
From JavaScript
var c = require('@cobuskruger/combine-files');
const result = c.combineFiles(['./test/test1.txt', './test/test2.txt'], config);
From TypeScript
import { combineFiles } from '@cobuskruger/combine-files';
const result = c.combineFiles(['./test/test1.txt', './test/test2.txt'], config);
Result
In both cases, result
will contain the combined test of all the files in the supplied array.
import { combineFiles } from '@cobuskruger/combine-files';
const result = combineFiles([], { includeToc: false, fileGlobs: ['**/*.sql'] }, './test');
Result
result
contains the combined text of all the .sql
files in '/test
and all its subfolders.
import { combineFiles } from '@cobuskruger/combine-files';
const result = combineFiles([], {
fileGlobs: ['**/*.sql'],
outputFileName: './test/output.sql' }, './test');
import { combineFiles } from '@cobuskruger/combine-files';
const result = combineFiles([], {
fileGlobs: [
'**/*.sql'
],
outputFileName: './test/output.sql'
fileHeader: [
"/* This text is placed at the very top of the output file, before the",
" table of contents and input file content. You can add multiple lines",
" and they will be separated by EOL markers. You can also optionally ",
" use ${now} to insert the current date and time.",
"*/"
],
includeToc: true,
tocHeader: [
"/* This will be placed directly below the file header when includeToc === true"
],
tocEntry: "* ${lineNo}\t\t${entryPath}",
tocFooter: [
"* This will be placed below the last of the TOC entries",
"*/"
],
entryHeader: [
"/* An 'entry' is the content of one of the input files, or a file matching any",
" * fileGlobs entry. ",
" * This is the block of text that will be added to the top of each entry.",
" * You can make it more useful, by using a variable, as shown below.",
" */",
"print 'Start: ${entryPath}'",
"GO"
],
entryFooter: [
"/* This text is placed at the bottom of each entry.
],
fileFooter: [
"/* This text is placed at the very end of the output file. */",
"GO"
"print 'Start: ${entryPath}'",
"GO"
],
}, './test');
Apart from the simple combineFiles
function, you can also use the various exported classes directly, which provides extra capabilities.
Given the following folder structure:
some
folder
file1.spec.ts
file2.spec.ts
other
folder
file3.spec.ts
file4.spec.ts
unrelated1
file5.spec.ts
file6.spec.ts
unrelated2
file7.spec.ts
unrelated3
folder1
file8.spec.ts
folder2
file9.spec.ts
tests.js
This listing will find tests in a selection of subfolders:
import { combineFiles, FileList } from '@cobuskruger/combine-files';
const files = new FileList(['some/folder', 'some/other/folder', './tests.js'], './', {
fileGlobs: ['**/*.spec.*s']
});
combineFiles(files.list, config);
The list of files passed to combineFiles
will be:
- ./some/folder/file1.spec.ts
- ./some/folder/file2.spec.ts
- ./some/other/folder/file3.spec.ts
- ./some/other/folder/file4.spec.ts
- ./tests.js
If you want to reuse file or entry headers and footers, you can do so by overriding the default configuration:
FileCombiner.defaultConfigGroup = {
entryFooter: ['/* End: ${entryPath} */'],
entryHeader: ['/* Start: ${entryPath} */'],
fileFooter: ['/* The end */'],
fileHeader: ['/* The start */'],
includeToc: true,
tocEntry: '/*\t${lineNo}\t\t${entryPath} */',
tocFooter: ['/* Table of Contents */'],
tocHeader: [],
};
If you supply a default, that will be combined with each individual fileGroups
entry. Values you specify in a fileGroupEntry
will override the values in the default.
function combineFiles(
fileList: string[],
fileGroup: IConfigFileGroup,
rootPath?: string
): string
Parameters
fileList
- A list of files or folders to include. Files are included as-is, while folders are searched for candidate files according to the globs listed in thefileGroup
.fileGroup
- AnIConfigFileGroup
instance, which controls how to combine the files.rootPath
- All other paths are considered relative to this path. If omitted, defaults to the current directory.
Return Value
Returns the combined text of all the files, taking into account header, footer and TOC configuration.
Side Effects
If the fileGroup
parameter has an outputFileName
specified, this function creates that file containing the combined text.
This class is used internally and can combine the files specified in fileList. The result is returned in getText()
.
export class FileCombiner {
public static defaultConfigGroup: IConfigFileGroup;
constructor(private fileGroup: IConfigFileGroup, fileList: string[]);
public getText();
}
This class receives a list of input files and folders, applies the fileGlobs
specified and returns a list of matching files in the list
property.
export class FileList {
public get list(): string[];
constructor(
pathList: string[],
rootPath: string,
fileGroup: IConfigFileGroup
);
public addFilesToList(pathName: string);
}
Represents the configuration used to search for files to include and how to combine them.
export interface IConfigFileGroup {
groupName?: string;
outputFileName?: string;
fileGlobs?: string[];
fileHeader?: string[];
fileFooter?: string[];
includeToc?: boolean;
tocHeader?: string[];
tocEntry?: string;
tocFooter?: string[];
entryHeader?: string[];
entryFooter?: string[];
}
All the properties are optional.
groupName
- Not used. Use this to label multiple configurations.outputFileName
- The name of the output file. No file is written if this is not specified.fileGlobs
- A list of glob patterns to match. A file is included if it matches any glob pattern. Defaults to*.*
if none is specified.fileHeader
- The lines of text to be placed at the beginning of the output. Defaults to empty array.fileFooter
- The lines of text to be placed at the end of the output. Defaults to empty array.includeToc
- A table of contents will be written afterfileHeader
but before the firstentryHeader
if this istrue
. Defaults tofalse
.tocHeader
- IfincludeToc === true
, the lines of text to be placed after thefileHeader
, but before the firsttocEntry
. Defaults to empty array.tocEntry
- IfincludeToc === true
, the single line of text that is added once for each included file. Defaults to'\t${lineNo}\t\t${entryPath}'
, which will show the line number and original file name for each entry.tocFooter
- IfincludeToc === true
, the lines of text to be placed after the lasttocEntry
, but before the firstentryHeader
. Defaults to empty array.entryHeader
- The lines of text to be placed at the beginning of each file entry. You can also include the${entryPath}
variable anywhere in this value. Defaults to empty array.entryFooter
- The lines of text to be placed at the end of each file entry. You can also include the${entryPath}
variable anywhere in this value. Defaults to empty array.
- Combine Scripts for Azure Data Studio is an extension for Microsoft Azure Data Studio that uses this to concatenate SQL script files. Supports configuration files and the ability to run several configurations in one action.
- Combine Files for Visual Studio Code is an extension for Microsoft Visual Studio Code that uses this to concatenate files of many kinds. Supports configuration files and the ability to run several configurations in one action.
MIT