var fs = require('fs'); | |
var path = require('path'); | |
var common = require('./common'); | |
//@ | |
//@ ### mv(source [, source ...], dest') | |
//@ ### mv(source_array, dest') | |
//@ Available options: | |
//@ | |
//@ + `f`: force | |
//@ | |
//@ Examples: | |
//@ | |
//@ ```javascript | |
//@ mv('-f', 'file', 'dir/'); | |
//@ mv('file1', 'file2', 'dir/'); | |
//@ mv(['file1', 'file2'], 'dir/'); // same as above | |
//@ ``` | |
//@ | |
//@ Moves files. The wildcard `*` is accepted. | |
function _mv(options, sources, dest) { | |
options = common.parseOptions(options, { | |
'f': 'force' | |
}); | |
// Get sources, dest | |
if (arguments.length < 3) { | |
common.error('missing <source> and/or <dest>'); | |
} else if (arguments.length > 3) { | |
sources = [].slice.call(arguments, 1, arguments.length - 1); | |
dest = arguments[arguments.length - 1]; | |
} else if (typeof sources === 'string') { | |
sources = [sources]; | |
} else if ('length' in sources) { | |
sources = sources; // no-op for array | |
} else { | |
common.error('invalid arguments'); | |
} | |
sources = common.expand(sources); | |
var exists = fs.existsSync(dest), | |
stats = exists && fs.statSync(dest); | |
// Dest is not existing dir, but multiple sources given | |
if ((!exists || !stats.isDirectory()) && sources.length > 1) | |
common.error('dest is not a directory (too many sources)'); | |
// Dest is an existing file, but no -f given | |
if (exists && stats.isFile() && !options.force) | |
common.error('dest file already exists: ' + dest); | |
sources.forEach(function(src) { | |
if (!fs.existsSync(src)) { | |
common.error('no such file or directory: '+src, true); | |
return; // skip file | |
} | |
// If here, src exists | |
// When copying to '/path/dir': | |
// thisDest = '/path/dir/file1' | |
var thisDest = dest; | |
if (fs.existsSync(dest) && fs.statSync(dest).isDirectory()) | |
thisDest = path.normalize(dest + '/' + path.basename(src)); | |
if (fs.existsSync(thisDest) && !options.force) { | |
common.error('dest file already exists: ' + thisDest, true); | |
return; // skip file | |
} | |
if (path.resolve(src) === path.dirname(path.resolve(thisDest))) { | |
common.error('cannot move to self: '+src, true); | |
return; // skip file | |
} | |
fs.renameSync(src, thisDest); | |
}); // forEach(src) | |
} // mv | |
module.exports = _mv; |