$ cnpm install sync-directory
sync-directory can sync files from src directory to target directory.
CLI and API are supported.
We have two ways to sync files: hardlink and copy.
If type is copy, sync-directory will copy files from src directory to target directory.
If type is hardlink, sync-directory can create hardlink files in target directory from src directory.
sync-directory uses copy by default for safety. (hardlink will be quicker but some watchers can't trigger change event for target files.)
npm i sync-directory -g
syncdir <from> <to> [options]
Example: syncdir aaa bbb -w
options:
-w, --watch
Watch changes. false as default.
Same as config watch.
--quiet
Disable unnecessary logs.
--exclude <strings...>
Exclude some path. Such as syncdir a b --exclude node_modules package-lock.json.
Same as config exclude
-si, --skipInitialSync
Skip the first time sync actions when it's true. It's useful when you just want the srcFolder to be watched. false as default.
Same as config skipInitialSync.
-nd, --nodeep
Just walk the first level sub files/folders. Avoids deep scanning of big folders.
Same as config nodeep.
-do, --deleteOrphaned
Delete orphaned or excluded (when using API) files/folders in target folder. false as default.
Same as config deleteOrphaned.
-hardlink, --hardlink
Sync with type hardlink, copy as default.
Same as config type: 'hardlink'.
-symlink, --symlink
support symlink while sync running. false as default.
Same as config staySymlink.
commonjs
const syncDirectory = require('sync-directory');
esm
import syncDirectory from 'sync-directory/index.mjs'
syncDirectory(srcDir, targetDir, {
afterEachSync({ eventType, nodeType, relativePath, srcPath, targetPath }) {
},
});
commonjs
const { async } = require('sync-directory');
esm
import { async } from 'sync-directory/index.mjs'
(async () => {
const delay = (time = 2000) => new Promise(r => setTimeout(r, time));
console.log('start'); // time a
// wait several 2s: 2 * file number
await async(srcDir, targetDir, {
async afterEachSync({ eventType, nodeType, relativePath, srcPath, targetPath }) {
await delay(2000); // delay 2s after one file/folder was synced
},
});
console.log('end'); // time a + 2 * (file number)
})()
commonjs
const syncDirectory = require('sync-directory');
esm
import syncDirectory from 'sync-directory/index.mjs';
syncDirectory(srcDir, targetDir[, config]);
| Function | Returns | Syntax | Block the thread? |
|---|---|---|---|
syncDirectory()syncDirectory.sync() |
undefined or chokidar watcher |
Synchronous | Yes |
syncDirectory.async() |
Promise |
async / awaitPromise.then() |
No |
const watcher = syncDirectory(A, B);
watcher is undefined.
const watcher = syncDirectory(A, B, {
watch: true
});
watcher is a chokidar watcher.
| name | description | type | values | default | can be async ? |
|---|---|---|---|---|---|
srcDir |
src directory | String | absolute or relative path | - | - |
targetDir |
target directory | String | absolute or relative path | - | - |
config.cwd |
when srcDir or targetDir is a relative path, they will be formatted to absolute path by path.join(cwd, srcDir | targetDir) |
string | - | process.cwd() |
- |
config.watch |
watch file changes | Boolean | - | false | - |
config.chokidarWatchOptions |
watch options (chokidar is used for watching) | Object | - | {} |
- |
config.type |
way to sync files | String | 'copy' \| 'hardlink' |
'copy' |
- |
config.skipInitialSync |
skip the first time sync actions when it's true. It's useful when you just want the srcFolder to be watched. |
Boolean | true \| false |
false |
- |
config.deleteOrphaned |
delete orphaned or excluded (API using) files/folders in target folder. false as default. |
Boolean | - | false |
- |
config.afterEachSync |
callback function when every file synced | Function | - | blank function | Yes when syncDirectory.async() |
config.staySymlink |
if src folder "A/" is a symlink, the target folder "A/" will also be the same symlink. | Boolean | - | false | - |
config.stayHardlink |
only worked when type: 'hardlink'. When stayHardlink: true, if src file is "src/a.js", the target file "target/a.js" will be a hardlink of "src/a.js". |
Boolean | - | true |
- |
config.exclude |
Priority: forceSync > exclude. Filter which src files should not be synced. |
RegExp / String / Array (item is RegExp / String) | - | null | - |
config.forceSync |
Priority: forceSync > exclude. Force sync some files even though they are excluded. |
RegExp / String / Array (item is RegExp / String) | - | (file) => { return false } |
No |
config.nodeep |
Just walk the first level sub files/folders. | Boolean | - | false |
- |
config.onError |
callback function when something wrong | Function | - | (err) => { throw new Error(err) } |
Yes when syncDirectory.async() |

cwd
Type: String
Default: process.cwd()
For: format srcDir | targetDir to absolute path when they are relative paths
syncDirectory(srcDir, targetDir, {
cwd: __dirname
});
watch
Type: true | false
Default: false
For: watch file changes.
syncDirectory(srcDir, targetDir, {
watch: true
});
chokidarWatchOptions
Type: Object
Default: {}
For: watch options (chokidar is used for watching).
syncDirectory(srcDir, targetDir, {
chokidarWatchOptions: {
awaitWriteFinish: {
stabilityThreshold: 2000,
pollInterval: 100
}
},
});
afterEachSync
Type: Function
Default: () => {}
For: callback function when every file synced.
syncDirectory.sync(srcDir, targetDir, {
afterEachSync({ eventType, nodeType, relativePath, srcPath, targetPath }) {
}
});
await syncDirectory.async(srcDir, targetDir, {
async afterEachSync({ eventType, nodeType, relativePath, srcPath, targetPath }) {
}
});
eventType: "init:hardlink" / "init:copy" / "add" / "change" / "unlink" / "unlinkDir" / "addDir"nodeType: "file" / "dir"relativePath: relative file/folder pathsrcPath: absolute or relative src file/folder pathtargetPath: absolute or relative target file/folder pathtype
Type: 'copy' | 'hardlink'
Default: 'copy'
For: way to sync files.
copy (default)
syncDirectory(srcDir, targetDir);
hardlink
syncDirectory(srcDir, targetDir, {
type: 'hardlink'
});
skipInitialSync
Type: true | false
Default: false
For: enhance the performance
It's for enhancing the sync performance when you just want srcDir to be watched.
syncDirectory(srcDir, targetDir, {
skipInitialSync: true,
watch: true,
})
The srcDir won't be synced to targetDir when skipInitialSync: true and the srcDir's file changes will be watched and synced to targetDir.
stayHardlink
Type: true | false
Default: true
Only works when type: 'hardlink'.
When stayHardlink: true, if src file is "src/a.js", the target file "target/a.js" will be a hardlink of "src/a.js".
Then when "src/a.js" changed, "target/a.js" will remain a hardlink. Otherwise will be a copied file.
Some watchers will not be able to watch changes of "target/a.js".
nodeep
Type: true | false
Default: false
Just walk the first level sub files/folders. Avoids deep scanning of big folders.
The reason why
deepwas not used is that cli options is--nodeep. Just keep this two the same.
// srcFolder:
// a/ a is symlink
// 1.js
// targetFolder:
// a/
syncDirectory(srcDir, targetDir, {
nodeep: true, // 1.js will be ignored
});
deleteOrphaned
Type: true | false
Default: false
Delete orphaned or excluded (when using API) files/folders in target folder. false as default.
For instance:
srcDir:
dir1/
1.js
2.js
targetDir:
dir2/
1.js
2.js
3.js
syncDirectory(srcDir, targetDir, {
deleteOrphaned: true,
excluded: [ '2.js' ]
});
// dir2/3.js will be removed because dir1/3.js does not exist.
// dir2/2.js will be removed because dir1/2.js is excluded.
exclude
Type: Function / RegExp / String / Array (item is RegExp / String)
Priority: forceSync > exclude.
Default: null
For: declare files that should not sync to target directory.
Function
syncDirectory(srcDir, targetDir, {
exclude(filePath) {
return /node_modules/.test(filePath);
}
});
String
syncDirectory(srcDir, targetDir, {
exclude: 'node_modules'
});
RegExp
syncDirectory(srcDir, targetDir, {
exclude: /node\_modules/
});
Array
syncDirectory(srcDir, targetDir, {
exclude: [/node\_modules/]
});
syncDirectory(srcDir, targetDir, {
exclude: ['node_modules']
});
forceSync
Type: Function / RegExp / String / Array (item is RegExp / String)
Priority: forceSync > exclude.
Default: null
For: some files must be synced even though 'excluded'.
Function
syncDirectory(srcDir, targetDir, {
exclude: ['node_modules'],
forceSync(filePath) {
return /node_modules\/jquery/.test(filePath);
}
});
String
syncDirectory(srcDir, targetDir, {
exclude: ['node_modules'],
forceSync: 'node_modules/jquery'
});
RegExp
syncDirectory(srcDir, targetDir, {
exclude: ['node_modules'],
forceSync: /node_modules\/jquery/
});
Array
syncDirectory(srcDir, targetDir, {
exclude: ['node_modules'],
forceSync: [/node_modules\/jquery/]
});
syncDirectory(srcDir, targetDir, {
exclude: ['node_modules'],
forceSync: ['node_modules/jquery']
});
staySymlink
Type: true | false
Default: false
If src folder "A/" is a symlink, the target folder "A/" will also be the same symlink.
// srcFolder:
// a/ a is symlink
// 1.js
// targetFolder:
// a/ a is not symlink
// 1.js
syncDirectory(srcDir, targetDir, {
staySymlink: false,
});
// srcFolder:
// a/ a is symlink
// 1.js
// targetFolder:
// a/ a is the same symlink
// 1.js
syncDirectory(srcDir, targetDir, {
staySymlink: true,
});
onError
Type: Function
Default: (err) => { throw new Error(err) }
For: callback function when something wrong.
syncDirectory(srcDir, targetDir, {
onError(err) {
console.log(err.message);
},
});
MIT
Copyright 2013 - present © cnpmjs.org | Home |