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 / await Promise.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 pathssyncDirectory(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 path
-
type
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 totargetDir
whenskipInitialSync: true
and thesrcDir
's file changes will be watched and synced totargetDir
. -
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
deep
was 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