Como mover arquivos no node.js?

151

Como posso mover arquivos (como o shell de comando mv) no node.js? Existe algum método para isso ou devo ler um arquivo, gravar em um novo arquivo e remover o arquivo mais antigo?

rizidoro
fonte

Respostas:

157

De acordo com o comentário seppo0010, usei a função renomear para fazer isso.

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

fs.rename (oldPath, newPath, retorno de chamada)

Adicionado em: v0.0.2

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

Renomeação assíncrona (2). Nenhum argumento além de uma possível exceção é fornecido ao retorno de chamada de conclusão.

rizidoro
fonte
5
Para aqueles que se perguntam para onde foi o comentário do @ seppo0010: foi na minha resposta que eu apaguei e postei como um comentário no OP.
Matt Bola
6
Isso não funcionará se você estiver cruzando partições ou usando um sistema de arquivos virtual que não suporta arquivos em movimento. É melhor usar esta solução com um fallback cópia
Flavien Volken
A terceira resposta de "Hani" possui um código de exemplo!
Nathan
47

Este exemplo foi retirado de: Node.js em ação

Uma função move () que renomeia, se possível, ou volta 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
fonte
3
Funcionou como um encanto. Obrigado! Se posso adicionar um pouco: 'move' pode ser um nome melhor quando ele desativa o oldPath.
Jokester
A função copy () está correta nesse caso, mas se alguém desejar envolvê-la dentro de um objeto Promise, consulte minha "resposta" abaixo ou lembre-se de resolver a promessa do evento "close" no fluxo de gravação, não no fluxo de leitura.
Jem
Parece algo que funcionará para minhas necessidades, no entanto, não sei como usar o estilo module.exports = function {}. copio esse código no meu próprio aplicativo, onde já tenho var fs = require ('fs'); e chame fs.move (oldFile, newFile, function (err) {....}) em vez de fs.rename?
precisa saber é o seguinte
@ Curious101 Você pode colocar isso em um arquivo como filemove.js e importá-lo como var filemove = require ('filemove'); depois use-o como um arquivo (...);
Teoman shipahi #
Obrigado @Teomanshipahi. Nesse caso, posso adicionar ao mylibrary.js e usá-lo a partir daí. Eu pensei que este era um método bem conhecido de adicionar métodos de protótipo para que fique disponível no próprio objeto.
precisa saber é o seguinte
35

Usando nodejs nativamente

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!')
})

(OBSERVAÇÃO: "Isso não funcionará se você estiver cruzando partições ou usando um sistema de arquivos virtual que não suporta arquivos em movimento. [...]" - Flavien Volken 2 de setembro de '15 às 12:50 ")

Hani
fonte
30

Use o módulo do nó mv , que primeiro tentará fazer um fs.renamee, em seguida, fará o fallback para copiar e depois desvincular.

andrewrk
fonte
Funcionou bem para os requisitos simples de mover um arquivo.
Arcseldon
1
andrewrk parece ser o autor deste mvmódulo de nó. Eu gosto de usar o npm para instalar; npm install mv --save-dev; aqui está o link npm
The Red Pea
3
Como isso é uma dependência de desenvolvedor? O aplicativo não requer mv para funcionar?
jgr0
17

util.pump foi descontinuado no nó 0.10 e gera mensagem de aviso

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

Portanto, a solução para copiar arquivos usando fluxos é:

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 */ });
morto
fonte
2
Essa é a maneira correta de copiar / mover um arquivo que está em duas partições diferentes. Obrigado!
slickplaid
9

Usando a função renomear:

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

Onde

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

assumindo que você deseja manter o nome do arquivo inalterado.

Iulia
fonte
4
Tenha cuidado para isso não vai funcionar se você tentar mudar o nome do arquivo entre diferentes partições, nem em alguns sistemas de arquivos virtuais (como estivador por exemplo)
Flavien Volken
8

O fs-extramódulo permite que você faça isso com seu move()método. Eu já o implementei e funciona bem se você deseja mover completamente um arquivo de um diretório para outro - ou seja. removendo o arquivo do diretório de origem. Deve funcionar para os casos mais 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
fonte
5

Aqui está um exemplo usando util.pump, de >> Como mover o arquivo a para uma partição ou dispositivo diferente no 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
fonte
20
Vale a pena notar que você só precisa fazer isso ao mover arquivos entre volumes. Caso contrário, você pode simplesmente usar fs.rename()(em um volume renomear um arquivo e movê-lo é a mesma coisa).
S4y
4
util.pump está obsoleto.
andrewrk
É possível mover o arquivo da máquina local para o servidor?
Hulk1991
Não, você precisa usar outra coisa para isso (como usar FTP, HTTP ou outro protocolo).
Alessioalex 31/07/2013
4

Usando promessas para versões de nó maiores que 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
fonte
3
Apenas uma palavra de cautela fs.renamenão funcionará se você estiver em um ambiente Docker com volumes.
Atul Yadav
Adicione uma asyncdeclaração à moveThemfunção.
H_I 24/08/19
3

Apenas meus 2 centavos, conforme indicado na resposta acima : O método copy () não deve ser usado como está para copiar arquivos sem um pequeno 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);
}

A função de cópia envolvida em uma promessa:

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);
  })

No entanto, lembre-se de que o sistema de arquivos pode falhar se a pasta de destino não existir.

Jem
fonte
3

Gostaria de separar todas as funções envolvidas (ie rename, copy, unlink) um do outro para ganhar flexibilidade e tudo promisify, é claro:

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 é apenas uma função de conveniência e podemos aplicar as funções separadamente, quando, por exemplo, precisamos de um tratamento de exceção mais refinado.


fonte
2

Shelljs é uma solução muito útil.

comando: mv ([opções,] origem, destino)

Opções disponíveis:

-f: force (comportamento padrão)

-n: para evitar a substituição

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
fonte
1

essa é uma repetição da resposta de teoman shipahi com um nome um pouco menos ambíguo e seguindo o princípio de design da definição do código antes de você tentar chamá-lo. (Embora o nó permita que você faça o contrário, não é uma boa prática colocar a carroça diante do cavalo.)

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();
        }
    );
}
não sincronizado
fonte
0

Com a ajuda do URL abaixo, você pode copiar ou mover o arquivo Origem atual para a Origem 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
fonte
-1

Se você estiver tentando mover ou renomear um arquivo de origem node.js., tente este https://github.com/viruschidai/node-mv . Ele atualizará as referências a esse arquivo em todos os outros arquivos.

William
fonte
-6

Você pode usar o move-file pacote npm:

Primeiro instale o pacote:

$ 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
fonte
Curto e resposta inteligente, Bom @paridhishah
Abdullah Pariyani
2
Essa é uma chamada para uma função que ainda não foi criada; portanto, apenas gera um erro.
Steve Carey