What is recursive-copy?
The recursive-copy npm package is a utility for copying files and directories recursively with support for filtering, transforming, and other advanced options.
What are recursive-copy's main functionalities?
Basic Copy
This feature allows you to copy files and directories from a source to a destination. The code sample demonstrates a basic copy operation where files from the 'source' directory are copied to the 'destination' directory.
const copy = require('recursive-copy');
copy('source', 'destination')
.then(function(results) {
console.info('Copied ' + results.length + ' files');
})
.catch(function(error) {
console.error('Copy failed: ' + error);
});
Filtering Files
This feature allows you to filter which files to copy using glob patterns. The code sample demonstrates copying only JavaScript files except for test files.
const copy = require('recursive-copy');
copy('source', 'destination', {
filter: ['**/*.js', '!**/*.test.js']
})
.then(function(results) {
console.info('Copied ' + results.length + ' files');
})
.catch(function(error) {
console.error('Copy failed: ' + error);
});
Transforming Files
This feature allows you to transform files during the copy process. The code sample demonstrates transforming text files to uppercase while copying.
const copy = require('recursive-copy');
const fs = require('fs');
copy('source', 'destination', {
transform: function(src, dest, stats) {
if (src.endsWith('.txt')) {
return through(function(chunk, enc, done) {
this.push(chunk.toString().toUpperCase());
done();
});
}
}
})
.then(function(results) {
console.info('Copied ' + results.length + ' files');
})
.catch(function(error) {
console.error('Copy failed: ' + error);
});
Other packages similar to recursive-copy
ncp
The ncp (Node Copy) package is another utility for copying files and directories. It is simpler and has fewer features compared to recursive-copy, focusing mainly on basic copy operations without advanced filtering or transforming options.
fs-extra
The fs-extra package extends the native Node.js fs module with additional methods, including recursive copy. It provides a more comprehensive set of file system utilities compared to recursive-copy, but may be overkill if you only need basic copy functionality.
cpx
The cpx package is a command-line tool and library for copying files and directories with support for glob patterns. It is similar to recursive-copy in terms of filtering capabilities but also includes a CLI for easier use in scripts and command-line operations.
recursive-copy
Simple, flexible file copy utility
Features
- Recursively copy whole directory hierarchies
- Choose which files are copied by passing a filter function, regular expression or glob
- Rename files dynamically, including changing the output path
- Transform file contents using streams
- Choose whether to overwrite existing files
- Choose whether to copy system files
- Filters out junk files by default
- Uses graceful-fs and mkdirp to avoid filesystem errors
- Emits start, finish and error events for each file that is processed
- Optional promise-based interface
Examples
Node-style callback interface
var copy = require('recursive-copy');
copy('src', 'dest', function(error, results) {
if (error) {
console.error('Copy failed: ' + error);
} else {
console.info('Copied ' + results.length + ' files');
}
});
Promise interface
var copy = require('recursive-copy');
copy('src', 'dest')
.then(function(results) {
console.info('Copied ' + results.length + ' files');
})
.catch(function(error) {
console.error('Copy failed: ' + error);
});
ES2015+ usage
import copy from 'recursive-copy';
try {
const results = await copy('src', 'dest');
console.info('Copied ' + results.length + ' files');
} catch (error) {
console.error('Copy failed: ' + error);
}
Advanced options
var copy = require('recursive-copy');
var path = require('path');
var through = require('through2');
var options = {
overwrite: true,
expand: true,
dot: true,
junk: true,
filter: [
'**/*',
'!.htpasswd'
],
rename: function(filePath) {
return filePath + '.orig';
},
transform: function(src, dest, stats) {
if (path.extname(src) !== '.txt') { return null; }
return through(function(chunk, enc, done) {
var output = chunk.toString().toUpperCase();
done(null, output);
});
}
};
copy('src', 'dest', options)
.on(copy.events.COPY_FILE_START, function(copyOperation) {
console.info('Copying file ' + copyOperation.src + '...');
})
.on(copy.events.COPY_FILE_COMPLETE, function(copyOperation) {
console.info('Copied to ' + copyOperation.dest);
})
.on(copy.events.ERROR, function(error, copyOperation) {
console.error('Unable to copy ' + copyOperation.dest);
})
.then(function(results) {
console.info(results.length + ' file(s) copied');
})
.catch(function(error) {
return console.error('Copy failed: ' + error);
});
Usage
copy(src, dest, [options], [callback])
Recursively copy files and folders from src
to dest
Arguments:
Name | Type | Required | Default | Description |
---|
src | string | Yes | N/A | Source file/folder path |
dest | string | Yes | N/A | Destination file/folder path |
options.overwrite | boolean | No | false | Whether to overwrite destination files |
options.expand | boolean | No | false | Whether to expand symbolic links |
options.dot | boolean | No | false | Whether to copy files beginning with a . |
options.junk | boolean | No | false | Whether to copy OS junk files (e.g. .DS_Store , Thumbs.db ) |
options.filter | function , RegExp , string , array | No | null | Filter function / regular expression / glob that determines which files to copy (uses maximatch) |
options.rename | function | No | null | Function that maps source paths to destination paths |
options.transform | function | No | null | Function that returns a transform stream used to modify file contents |
options.results | boolean | No | true | Whether to return an array of copy results |
options.concurrency | number | No | 255 | Maximum number of simultaneous copy operations |
options.debug | boolean | No | false | Whether to log debug information |
callback | function | No | null | Callback, invoked on success/failure |
Returns:
Promise<Array>
Promise, fulfilled with array of copy results:
[
{
"src": "/path/to/src",
"dest": "/path/to/dest",
"stats": <Stats>
},
{
"src": "/path/to/src/file.txt",
"dest": "/path/to/dest/file.txt",
"stats": <Stats>
},
{
"src": "/path/to/src/subfolder",
"dest": "/path/to/dest/subfolder",
"stats": <Stats>
},
{
"src": "/path/to/src/subfolder/nested.txt",
"dest": "/path/to/dest/subfolder/nested.txt",
"stats": <Stats>
}
]
Events
The value returned by the copy
function implements the EventEmitter
interface, and emits the following events:
Event | Handler signature |
---|
copy.events.ERROR | function(error, ErrorInfo) |
copy.events.COMPLETE | function(Array<CopyOperation>) |
copy.events.CREATE_DIRECTORY_START | function(CopyOperation) |
copy.events.CREATE_DIRECTORY_ERROR | function(error, CopyOperation) |
copy.events.CREATE_DIRECTORY_COMPLETE | function(CopyOperation) |
copy.events.CREATE_SYMLINK_START | function(CopyOperation) |
copy.events.CREATE_SYMLINK_ERROR | function(error, CopyOperation) |
copy.events.CREATE_SYMLINK_COMPLETE | function(CopyOperation) |
copy.events.COPY_FILE_START | function(CopyOperation) |
copy.events.COPY_FILE_ERROR | function(error, CopyOperation) |
copy.events.COPY_FILE_COMPLETE | function(CopyOperation) |
...where the types referred to in the handler signature are as follows:
ErrorInfo
Property | Type | Description |
---|
src | string | Source path of the file/folder/symlink that failed to copy |
dest | string | Destination path of the file/folder/symlink that failed to copy |
CopyOperation
Property | Type | Description |
---|
src | string | Source path of the relevant file/folder/symlink |
dest | string | Destination path of the relevant file/folder/symlink |
stats | fs.Stats | Stats for the relevant file/folder/symlink |