Skip to content

Instantly share code, notes, and snippets.

@yuanyan
Last active December 18, 2015 17:39
Show Gist options
  • Save yuanyan/5819885 to your computer and use it in GitHub Desktop.
Save yuanyan/5819885 to your computer and use it in GitHub Desktop.
var fs = require("fs");
var path = require("path");
// mian code, 请替换路径地址
ncp('./path/to/source', './path/to/dest', function(){
rmrf('./path/to/source');
})
// copy from ncp, 请折叠
function ncp (source, dest, options, callback) {
if (!callback) {
callback = options;
options = {};
}
var basePath = process.cwd(),
currentPath = path.resolve(basePath, source),
targetPath = path.resolve(basePath, dest),
filter = options.filter,
transform = options.transform,
clobber = options.clobber !== false,
errs = null,
started = 0,
finished = 0,
running = 0,
limit = options.limit || ncp.limit || 16;
limit = (limit < 1) ? 1 : (limit > 512) ? 512 : limit;
startCopy(currentPath);
function startCopy(source) {
started++;
if (filter) {
if (filter instanceof RegExp) {
if (!filter.test(source)) {
return cb(true);
}
}
else if (typeof filter === 'function') {
if (!filter(source)) {
return cb(true);
}
}
}
return getStats(source);
}
function defer(fn) {
if (typeof(setImmediate) === 'function')
return setImmediate(fn);
return process.nextTick(fn);
}
function getStats(source) {
if (running >= limit) {
return defer(function () {
getStats(source);
});
}
running++;
fs.lstat(source, function (err, stats) {
var item = {};
if (err) {
return onError(err);
}
// We need to get the mode from the stats object and preserve it.
item.name = source;
item.mode = stats.mode;
if (stats.isDirectory()) {
return onDir(item);
}
else if (stats.isFile()) {
return onFile(item);
}
else if (stats.isSymbolicLink()) {
// Symlinks don't really need to know about the mode.
return onLink(source);
}
});
}
function onFile(file) {
var target = file.name.replace(currentPath, targetPath);
isWritable(target, function (writable) {
if (writable) {
return copyFile(file, target);
}
if(clobber)
rmFile(target, function () {
copyFile(file, target);
});
});
}
function copyFile(file, target) {
var readStream = fs.createReadStream(file.name),
writeStream = fs.createWriteStream(target, { mode: file.mode });
if(transform) {
transform(readStream, writeStream,file);
} else {
readStream.pipe(writeStream);
}
readStream.once('end', cb);
}
function rmFile(file, done) {
fs.unlink(file, function (err) {
if (err) {
return onError(err);
}
return done();
});
}
function onDir(dir) {
var target = dir.name.replace(currentPath, targetPath);
isWritable(target, function (writable) {
if (writable) {
return mkDir(dir, target);
}
copyDir(dir.name);
});
}
function mkDir(dir, target) {
fs.mkdir(target, dir.mode, function (err) {
if (err) {
return onError(err);
}
copyDir(dir.name);
});
}
function copyDir(dir) {
fs.readdir(dir, function (err, items) {
if (err) {
return onError(err);
}
items.forEach(function (item) {
startCopy(dir + '/' + item);
});
return cb();
});
}
function onLink(link) {
var target = link.replace(currentPath, targetPath);
fs.readlink(link, function (err, resolvedPath) {
if (err) {
return onError(err);
}
checkLink(resolvedPath, target);
});
}
function checkLink(resolvedPath, target) {
isWritable(target, function (writable) {
if (writable) {
return makeLink(resolvedPath, target);
}
fs.readlink(target, function (err, targetDest) {
if (err) {
return onError(err);
}
if (targetDest === resolvedPath) {
return cb();
}
return rmFile(target, function () {
makeLink(resolvedPath, target);
});
});
});
}
function makeLink(linkPath, target) {
fs.symlink(linkPath, target, function (err) {
if (err) {
return onError(err);
}
return cb();
});
}
function isWritable(path, done) {
fs.lstat(path, function (err, stats) {
if (err) {
if (err.code === 'ENOENT') return done(true);
return done(false);
}
return done(false);
});
}
function onError(err) {
if (options.stopOnError) {
return callback(err);
}
else if (!errs && options.errs) {
errs = fs.createWriteStream(options.errs);
}
else if (!errs) {
errs = [];
}
if (typeof errs.write === 'undefined') {
errs.push(err);
}
else {
errs.write(err.stack + '\n\n');
}
return cb();
}
function cb(skipped) {
if (!skipped) running--;
finished++;
if ((started === finished) && (running === 0)) {
return errs ? callback(errs) : callback(null);
}
}
};
// rm -rf
var rmrf = function(dir) {
var list = fs.readdirSync(dir);
for(var i = 0; i < list.length; i++) {
var filename = path.join(dir, list[i]);
var stat = fs.statSync(filename);
if(stat.isDirectory())
rmrf(filename);
else
fs.unlinkSync(filename);
}
fs.rmdirSync(dir);
};
@yuanyan
Copy link
Author

yuanyan commented Jun 20, 2013

the error

E:\Winnie>node demo.js

fs.js:456
  return binding.rmdir(pathModule._makeLong(path));
                 ^
Error: ENOTEMPTY, directory not empty 'E:\Winnie\example
    at Object.fs.rmdirSync (fs.js:456:18)
    at rmrf (E:\Winnie\demo.js:15:8)
    at rmrf (E:\Winnie\demo.js:11:13)
    at rmrf (E:\Winnie\demo.js:11:13)
    at E:\Winnie\demo.js:19:5
    at cb (E:\Winnie\node_modules\ncp\lib\ncp.js:217:38)
    at g (events.js:185:14)
    at EventEmitter.emit (events.js:115:20)
    at afterRead (fs.js:1324:12)
    at Object.wrapper [as oncomplete] (fs.js:362:17)

node version

E:\Winnie>node -v
v0.8.9

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment