mv (Node.js)

2.1.1 · abandoned · verified Sun Apr 19

The `mv` package by `andrewrk` provides a robust utility for moving files and directories in Node.js, specifically addressing the limitation of `fs.rename` which cannot perform operations across different devices or file systems. It first attempts a standard `fs.rename` and, upon failure (e.g., cross-device boundary), transparently falls back to a copy-then-unlink strategy. For files, this involves piping data, and for directories, it utilizes a recursive copy (`ncp`) followed by removal of the source (`rimraf`). It supports options like automatically creating destination parent directories (`mkdirp: true`) and preventing overwrites (`clobber: false`). The current stable version, `2.1.1`, was released in 2015. Given its age and lack of recent updates, this package is considered abandoned. Developers are advised to consider actively maintained alternatives, such as `move-file`, which offer modern Promise-based APIs and enhanced ESM support, if possible.

Common errors

Warnings

Install

Imports

Quickstart

Demonstrates moving a file, moving a directory (with `mkdirp`), and handling the `EEXIST` error when attempting to overwrite a file with `clobber: false`.

const mv = require('mv');
const fs = require('fs');
const path = require('path');

async function runExample() {
  const sourceFile = path.join(__dirname, 'source.txt');
  const destFile = path.join(__dirname, 'dest', 'new-name.txt');
  const sourceDir = path.join(__dirname, 'old-dir');
  const destDir = path.join(__dirname, 'target', 'new-dir');

  // Ensure directories exist for testing
  fs.mkdirSync(path.join(__dirname, 'dest'), { recursive: true });
  fs.mkdirSync(sourceDir, { recursive: true });
  fs.writeFileSync(sourceFile, 'Hello from source file!');
  fs.writeFileSync(path.join(sourceDir, 'file-in-dir.txt'), 'Content in directory!');

  console.log('Moving a file...');
  await new Promise((resolve, reject) => {
    mv(sourceFile, destFile, function(err) {
      if (err) return reject(err);
      console.log('File moved successfully to', destFile);
      resolve();
    });
  });

  console.log('\nMoving a directory and creating parent path...');
  await new Promise((resolve, reject) => {
    mv(sourceDir, destDir, { mkdirp: true }, function(err) {
      if (err) return reject(err);
      console.log('Directory moved successfully to', destDir);
      resolve();
    });
  });

  const existingFile = path.join(__dirname, 'existing.txt');
  fs.writeFileSync(existingFile, 'This file exists.');
  const clashTarget = path.join(__dirname, 'existing.txt'); // Intentionally clash
  fs.writeFileSync(clashTarget, 'This will be clobbered unless clobber:false.');

  console.log('\nAttempting to move file with clobber: false (expecting EEXIST error)...');
  await new Promise((resolve) => {
    mv(sourceFile, clashTarget, { clobber: false }, function(err) {
      if (err) {
        console.error('Expected error when clobber: false:', err.code, err.message);
        // Clean up potentially clobbered file for next run if it wasn't the exact clash
        if (fs.existsSync(clashTarget)) fs.unlinkSync(clashTarget);
        resolve();
      } else {
        console.log('File moved without error when clobber: false (unexpected for this example).');
        resolve();
      }
    });
  }).catch(console.error);

  // Clean up created files/dirs
  if (fs.existsSync(sourceFile)) fs.unlinkSync(sourceFile);
  if (fs.existsSync(destFile)) fs.unlinkSync(destFile);
  if (fs.existsSync(sourceDir)) fs.rmSync(sourceDir, { recursive: true, force: true });
  if (fs.existsSync(destDir)) fs.rmSync(destDir, { recursive: true, force: true });
  if (fs.existsSync(path.join(__dirname, 'dest'))) fs.rmdirSync(path.join(__dirname, 'dest'));
  if (fs.existsSync(path.join(__dirname, 'target'))) fs.rmdirSync(path.join(__dirname, 'target'));
  if (fs.existsSync(existingFile)) fs.unlinkSync(existingFile);
}

runExample().catch(console.error);

view raw JSON →