Asynchronous recursive file copy utility for Node.js with configurable concurrency and filtering options.
npx @tessl/cli install tessl/npm-ncp@2.0.0ncp (Node Copy) is an asynchronous recursive file and directory copying utility for Node.js that serves as a pure JavaScript alternative to the Unix cp -r command. It provides both programmatic API and command-line interface functionality with advanced features like concurrency control, file filtering, streaming transforms, and flexible error handling.
npm install ncpconst ncp = require('ncp').ncp;Alternative import (equivalent):
const ncp = require('ncp');const ncp = require('ncp').ncp;
// Basic file/directory copying
ncp('/path/to/source', '/path/to/destination', function (err) {
if (err) {
return console.error(err);
}
console.log('Copy completed successfully!');
});
// With options
ncp(source, destination, {
filter: /\.js$/, // Only copy .js files
limit: 32, // Higher concurrency
clobber: false, // Don't overwrite existing files
stopOnErr: true // Stop on first error
}, function (err) {
if (err) {
return console.error(err);
}
console.log('Copy completed with options!');
});Asynchronously copies files and directories from source to destination with comprehensive options for controlling the copy behavior.
/**
* Copy files and directories asynchronously
* @param {string} source - Source file or directory path
* @param {string} dest - Destination file or directory path
* @param {function} callback - Completion callback function(err)
*/
function ncp(source, dest, callback);
/**
* Copy files and directories asynchronously with options
* @param {string} source - Source file or directory path
* @param {string} dest - Destination file or directory path
* @param {object} options - Copy options object
* @param {function} callback - Completion callback function(err)
*/
function ncp(source, dest, options, callback);Set global concurrency limit for all ncp operations.
/**
* Global concurrency limit for file system operations
* @type {number}
* @default 16
*/
ncp.limit = 16;Alternative way to access the ncp function.
/**
* Alternative access to the main ncp function
* @type {function}
*/
ncp.ncp;Control which files get copied using regular expressions or custom functions.
/**
* Filter files to be copied
* @typedef {RegExp|function} FilterOption
* @property {RegExp} filter - Regular expression to match file paths
* @property {function} filter - Function(filePath) returning boolean
*/
options.filter;Usage Examples:
// Regular expression filter - only copy .js files
const options = {
filter: /\.js$/
};
// Function filter - copy only files modified in last 24 hours
const options = {
filter: function(filePath) {
const stats = require('fs').statSync(filePath);
const dayAgo = Date.now() - (24 * 60 * 60 * 1000);
return stats.mtime.getTime() > dayAgo;
}
};Apply streaming transformations during the copy process.
/**
* Stream transformation function
* @typedef {function} TransformFunction
* @param {ReadableStream} readStream - Source file read stream
* @param {WritableStream} writeStream - Destination file write stream
* @param {object} file - File metadata object with name, mode, mtime, atime
*/
options.transform;Usage Example:
const options = {
transform: function(readStream, writeStream, file) {
if (file.name.endsWith('.txt')) {
// Transform text files to uppercase
readStream
.pipe(require('stream').Transform({
transform(chunk, encoding, callback) {
callback(null, chunk.toString().toUpperCase());
}
}))
.pipe(writeStream);
} else {
// Copy other files normally
readStream.pipe(writeStream);
}
}
};Control whether to overwrite existing destination files.
/**
* Whether to overwrite existing destination files
* @typedef {boolean} ClobberOption
* @default true
*/
options.clobber;Control how symbolic links are processed during copying.
/**
* Whether to follow symbolic links
* @typedef {boolean} DereferenceOption
* @default false
*/
options.dereference;Set the maximum number of concurrent file system operations.
/**
* Concurrency limit for file system operations
* @typedef {number} LimitOption
* @default 16
* @min 1
* @max 512
*/
options.limit;Control error handling behavior and error output destination.
/**
* Whether to stop on first error
* @typedef {boolean} StopOnErrOption
* @default false
*/
options.stopOnErr;
// Note: The CLI uses --stoponerr but the API uses stopOnErr
/**
* Error output destination
* @typedef {string|Stream} ErrorsOption
* @property {string} errs - File path for error logging
* @property {Stream} errs - Writable stream for error output
*/
options.errs;Transform destination file paths during copying.
/**
* Function to rename destination paths
* @typedef {function} RenameFunction
* @param {string} targetPath - Original destination path
* @returns {string} - Modified destination path
*/
options.rename;Only copy files if source is newer than destination.
/**
* Only copy if source file is newer than destination
* @typedef {boolean} ModifiedOption
* @default false
*/
options.modified;The ncp package includes a command-line tool for file copying operations.
ncp [source] [destination] [--filter=pattern] [--limit=N] [--stoponerr]# Set concurrency limit
--limit=16
# Set filter pattern (RegExp)
--filter=\\.js$
# Stop on first error
--stoponerrCLI Examples:
# Basic copy
ncp /source/path /dest/path
# Copy with concurrency limit
ncp /source/path /dest/path --limit=32
# Copy only JavaScript files
ncp /source/path /dest/path --filter=\\.js$
# Copy with error stopping
ncp /source/path /dest/path --stoponerrThe callback function receives different error types based on the stopOnError option:
/**
* Single error (when stopOnError is true)
* @typedef {Error} SingleError
* @property {string} message - Error description
* @property {string} stack - Error stack trace
*/
/**
* Multiple errors (when stopOnError is false)
* @typedef {Error[]} ErrorArray
* @property {Error[]} errors - Array of error objects
*/Common error conditions that may occur during copying:
dereference: true)Error Handling Examples:
ncp(source, dest, { stopOnErr: false }, function(err) {
if (Array.isArray(err)) {
console.error('Multiple errors occurred:');
err.forEach(function(error) {
console.error('- ' + error.message);
});
} else if (err) {
console.error('Single error:', err.message);
} else {
console.log('Copy completed successfully');
}
});
// Error logging to file
ncp(source, dest, {
stopOnErr: false,
errs: './copy-errors.log'
}, function(err) {
// Errors are also written to copy-errors.log
if (err) {
console.error('Errors occurred, check copy-errors.log');
}
});// Copy only recently modified files
ncp(source, dest, {
filter: function(filePath) {
const stats = require('fs').statSync(filePath);
const hourAgo = Date.now() - (60 * 60 * 1000);
return stats.mtime.getTime() > hourAgo;
},
modified: true // Additional timestamp check
}, callback);// Optimize for large file operations
ncp(source, dest, {
limit: 64, // Higher concurrency
clobber: true, // Overwrite without checks
dereference: false // Don't resolve symlinks
}, callback);// Safe copying with comprehensive error handling
ncp(source, dest, {
clobber: false, // Don't overwrite existing files
modified: true, // Only copy if newer
stopOnErr: false, // Continue on errors
errs: process.stderr, // Log errors to stderr
filter: function(filePath) {
// Skip hidden files and directories
return !require('path').basename(filePath).startsWith('.');
}
}, function(err) {
if (Array.isArray(err)) {
console.log(`Copy completed with ${err.length} errors`);
} else if (err) {
console.error('Copy failed:', err.message);
} else {
console.log('Copy completed successfully');
}
});