¿Cómo muevo archivos en node.js?

151

¿Cómo puedo mover archivos (como el comando mv shell) en node.js? ¿Hay algún método para eso o debería leer un archivo, escribir en un archivo nuevo y eliminar un archivo anterior?

rizidoro
fuente

Respuestas:

157

Según el comentario seppo0010, utilicé la función de cambio de nombre para hacer eso.

http://nodejs.org/docs/latest/api/fs.html#fs_fs_rename_oldpath_newpath_callback

fs.rename (oldPath, newPath, callback)

Añadido en: v0.0.2

oldPath <String> | <Buffer>
newPath <String> | <Buffer>
callback <Function>

Cambio de nombre asincrónico (2). No hay argumentos distintos de una posible excepción para la devolución de llamada de finalización.

rizidoro
fuente
55
Para aquellos que se preguntan dónde fue el comentario de @ seppo0010: fue en mi respuesta, que eliminé y publiqué como un comentario en el OP.
Matt Ball
66
Esto no funcionará si cruza particiones o utiliza un sistema de archivos virtual que no admite archivos en movimiento. Es mejor que use esta solución con una copia de respaldo
Flavien Volken
¡La tercera respuesta de "Hani" tiene un código de ejemplo!
Nathan
47

Este ejemplo tomado de: Node.js en acción

Una función move () que cambia el nombre, si es posible, o vuelve a copiar

var fs = require('fs');

module.exports = function move(oldPath, newPath, callback) {

    fs.rename(oldPath, newPath, function (err) {
        if (err) {
            if (err.code === 'EXDEV') {
                copy();
            } else {
                callback(err);
            }
            return;
        }
        callback();
    });

    function copy() {
        var readStream = fs.createReadStream(oldPath);
        var writeStream = fs.createWriteStream(newPath);

        readStream.on('error', callback);
        writeStream.on('error', callback);

        readStream.on('close', function () {
            fs.unlink(oldPath, callback);
        });

        readStream.pipe(writeStream);
    }
}
Teoman shipahi
fuente
3
Trabajado como un encanto. ¡Gracias! Si puedo agregar un poco: 'mover' podría ser un mejor nombre cuando desvincula oldPath.
Jokester
La función copy () está bien en este caso, pero si alguien quiere envolverla dentro de un objeto Promise, vea mi "respuesta" a continuación o tenga en cuenta para resolver la promesa sobre el evento "close" en la secuencia de escritura, no en la secuencia de lectura.
Jem
Esto parece algo que funcionará para mis necesidades, sin embargo, no sé cómo usar el estilo module.exports = function {}. copio este código en mi propia aplicación donde ya tengo var fs = require ('fs'); y luego llame a fs.move (oldFile, newFile, function (err) {....}) en lugar de fs.rename?
Curioso101
@ Curious101 Puede poner esto en un archivo como filemove.js e importarlo como var filemove = require ('filemove'); luego úsalo como filemove (...);
Teoman shipahi
Gracias @Teomanshipahi. En ese caso, puedo agregar a mylibrary.js y usarlo desde allí. Pensé que este era un método bien conocido de agregar métodos prototipo para que esté disponible en el objeto mismo.
Curioso101
35

Usar nodejs de forma nativa

var fs = require('fs')

var oldPath = 'old/path/file.txt'
var newPath = 'new/path/file.txt'

fs.rename(oldPath, newPath, function (err) {
  if (err) throw err
  console.log('Successfully renamed - AKA moved!')
})

(NOTA: "Esto no funcionará si está cruzando particiones o está utilizando un sistema de archivos virtual que no admite archivos en movimiento." [...] - Flavien Volken 2 de septiembre de 2015 a las 12:50 ")

Hani
fuente
30

Utilice el módulo de nodo mv , que primero intentará hacer una fs.renamecopia de seguridad y luego volver a copiar y luego desvincular.

andrewrk
fuente
Funcionó bien para los requisitos simples para mover un archivo.
arcseldon
1
andrewrk parece ser el autor de este mvmódulo de nodo. Me gusta usar npm para instalar; npm install mv --save-dev; aquí está el enlace npm
The Red Pea
3
¿Cómo es esto una dependencia de desarrollo? ¿La aplicación no requiere mv para funcionar?
jgr0
17

util.pump está en desuso en el nodo 0.10 y genera un mensaje de advertencia

 util.pump() is deprecated. Use readableStream.pipe() instead

Entonces, la solución para copiar archivos usando secuencias es:

var source = fs.createReadStream('/path/to/source');
var dest = fs.createWriteStream('/path/to/dest');

source.pipe(dest);
source.on('end', function() { /* copied */ });
source.on('error', function(err) { /* error */ });
muerto
fuente
2
Esta es la forma correcta de copiar / mover un archivo que está en dos particiones diferentes. ¡Gracias!
slickplaid
9

Usando la función renombrar:

fs.rename(getFileName, __dirname + '/new_folder/' + getFileName); 

dónde

getFilename = file.extension (old path)
__dirname + '/new_folder/' + getFileName

suponiendo que desea mantener el nombre del archivo sin cambios.

iulia
fuente
44
Tenga cuidado de que esto no funcione si intenta cambiar el nombre del archivo entre diferentes particiones, ni en algunos sistemas de archivos virtuales (como Docker, por ejemplo)
Flavien Volken
8

El fs-extramódulo le permite hacer esto con su move()método. Ya lo implementé y funciona bien si desea mover completamente un archivo de un directorio a otro, es decir. eliminando el archivo del directorio fuente. Debería funcionar para la mayoría de los casos básicos.

var fs = require('fs-extra')

fs.move('/tmp/somefile', '/tmp/does/not/exist/yet/somefile', function (err) {
 if (err) return console.error(err)
 console.log("success!")
})
mikeym
fuente
5

Aquí hay un ejemplo usando util.pump, desde >> ¿Cómo muevo el archivo a a una partición o dispositivo diferente en Node.js?

var fs = require('fs'),
    util = require('util');

var is = fs.createReadStream('source_file')
var os = fs.createWriteStream('destination_file');

util.pump(is, os, function() {
    fs.unlinkSync('source_file');
});
alessioalex
fuente
20
Vale la pena señalar que solo tiene que hacer esto al mover archivos a través de volúmenes. De lo contrario, solo puede usar fs.rename()(dentro de un volumen, cambiar el nombre de un archivo y moverlo es lo mismo).
s4y
44
util.pump está en desuso.
andrewrk
¿Es posible mover el archivo de la máquina local al servidor?
Hulk1991
No, necesitas usar algo más para eso (como usar FTP, HTTP u otro protocolo).
alessioalex
4

Uso de promesas para versiones de nodo superiores a 8.0.0:

const {promisify} = require('util');
const fs = require('fs');
const {join} = require('path');
const mv = promisify(fs.rename);

const moveThem = async () => {
  // Move file ./bar/foo.js to ./baz/qux.js
  const original = join(__dirname, 'bar/foo.js');
  const target = join(__dirname, 'baz/qux.js'); 
  await mv(original, target);
}

moveThem();
vorillaz
fuente
3
Solo una palabra de precaución fs.renameno funciona si está en un entorno Docker con volúmenes.
Atul Yadav
Agregue una asyncdeclaración a la moveThemfunción.
H_I
3

Solo mis 2 centavos como se indica en la respuesta anterior : el método copy () no debe usarse tal cual para copiar archivos sin un ligero ajuste:

function copy(callback) {
    var readStream = fs.createReadStream(oldPath);
    var writeStream = fs.createWriteStream(newPath);

    readStream.on('error', callback);
    writeStream.on('error', callback);

    // Do not callback() upon "close" event on the readStream
    // readStream.on('close', function () {
    // Do instead upon "close" on the writeStream
    writeStream.on('close', function () {
        callback();
    });

    readStream.pipe(writeStream);
}

La función de copia envuelta en una Promesa:

function copy(oldPath, newPath) {
  return new Promise((resolve, reject) => {
    const readStream = fs.createReadStream(oldPath);
    const writeStream = fs.createWriteStream(newPath);

    readStream.on('error', err => reject(err));
    writeStream.on('error', err => reject(err));

    writeStream.on('close', function() {
      resolve();
    });

    readStream.pipe(writeStream);
  })

Sin embargo, tenga en cuenta que el sistema de archivos podría fallar si la carpeta de destino no existe.

Jem
fuente
3

Me gustaría separar todas las funciones implicadas (es decir rename, copy, unlink) entre sí para ganar flexibilidad y promisify todo, por supuesto:

const renameFile = (path, newPath) => 
  new Promise((res, rej) => {
    fs.rename(path, newPath, (err, data) =>
      err
        ? rej(err)
        : res(data));
  });

const copyFile = (path, newPath, flags) =>
  new Promise((res, rej) => {
    const readStream = fs.createReadStream(path),
      writeStream = fs.createWriteStream(newPath, {flags});

    readStream.on("error", rej);
    writeStream.on("error", rej);
    writeStream.on("finish", res);
    readStream.pipe(writeStream);
  });

const unlinkFile = path => 
  new Promise((res, rej) => {
    fs.unlink(path, (err, data) =>
      err
        ? rej(err)
        : res(data));
  });

const moveFile = (path, newPath, flags) =>
  renameFile(path, newPath)
    .catch(e => {
      if (e.code !== "EXDEV")
        throw new e;

      else
        return copyFile(path, newPath, flags)
          .then(() => unlinkFile(path));
    });

moveFile es solo una función de conveniencia y podemos aplicar las funciones por separado, cuando, por ejemplo, necesitamos un manejo de excepciones más fino.


fuente
2

Shelljs es una solución muy útil.

comando: mv ([opciones,] origen, destino)

Opciones Disponibles:

-f: fuerza (comportamiento predeterminado)

-n: para evitar sobrescribir

const shell = require('shelljs');
const status = shell.mv('README.md', '/home/my-dir');
if(status.stderr)  console.log(status.stderr);
else console.log('File moved!');
Prayag k
fuente
1

Esta es una repetición de la respuesta de Teoman Shipahi con un nombre un poco menos ambiguo, y siguiendo el principio de diseño de la definición del código antes de intentar llamarlo. (Si bien el nodo le permite hacer lo contrario, no es una buena práctica poner el carro delante del caballo).

function rename_or_copy_and_delete (oldPath, newPath, callback) {

    function copy_and_delete () {
        var readStream = fs.createReadStream(oldPath);
        var writeStream = fs.createWriteStream(newPath);

        readStream.on('error', callback);
        writeStream.on('error', callback);
        readStream.on('close', 
              function () {
                fs.unlink(oldPath, callback);
              }
        );

        readStream.pipe(writeStream);
    }

    fs.rename(oldPath, newPath, 
        function (err) {
          if (err) {
              if (err.code === 'EXDEV') {
                  copy_and_delete();
              } else {
                  callback(err);
              }
              return;// << both cases (err/copy_and_delete)
          }
          callback();
        }
    );
}
no sincronizado
fuente
0

Con la ayuda de la URL a continuación, puede copiar o mover su archivo Origen ACTUAL al Origen de destino

https://coursesweb.net/nodejs/move-copy-file

/*********Moves the $file to $dir2 Start *********/
var moveFile = (file, dir2)=>{
  //include the fs, path modules
  var fs = require('fs');
  var path = require('path');

  //gets file name and adds it to dir2
  var f = path.basename(file);
  var dest = path.resolve(dir2, f);

  fs.rename(file, dest, (err)=>{
    if(err) throw err;
    else console.log('Successfully moved');
  });
};

//move file1.htm from 'test/' to 'test/dir_1/'
moveFile('./test/file1.htm', './test/dir_1/');
/*********Moves the $file to $dir2 END *********/

/*********copy the $file to $dir2 Start *********/
var copyFile = (file, dir2)=>{
  //include the fs, path modules
  var fs = require('fs');
  var path = require('path');

  //gets file name and adds it to dir2
  var f = path.basename(file);
  var source = fs.createReadStream(file);
  var dest = fs.createWriteStream(path.resolve(dir2, f));

  source.pipe(dest);
  source.on('end', function() { console.log('Succesfully copied'); });
  source.on('error', function(err) { console.log(err); });
};

//example, copy file1.htm from 'test/dir_1/' to 'test/'
copyFile('./test/dir_1/file1.htm', './test/');
/*********copy the $file to $dir2 END *********/

Abdullah Pariyani
fuente
-6

Puede usar el move-filepaquete npm:

Primero instale el paquete:

$ npm install move-file

Uso:

const moveFile = require('move-file');

// moveFile Returns a Promise that resolves when the file has been moved
moveFile('source/unicorn.png', 'destination/unicorn.png')
  .then(() => {/* Handle success */})
  .catch((err) => {/* Handle failure */});

// Or use async/await
(async () => {
    try {
      await moveFile('source/unicorn.png', 'destination/unicorn.png');
      console.log('The file has been moved');
    } catch (err) {
      // Handle failure
      console.error(err);
    }
})();
Paridhi shah
fuente
Respuesta corta e inteligente, buena @paridhishah
Abdullah Pariyani
2
Esa es una llamada a una función que aún no se ha creado, por lo que simplemente arrojará un error.
Steve Carey