Як перемістити файли в node.js?


151

Як я можу переміщувати файли (наприклад, командна оболонка mv) на node.js? Чи є якийсь метод для цього чи я повинен прочитати файл, записати в новий файл і видалити старіший файл?

Відповіді:


157

Відповідно до коментаря seppo0010, для цього я використовував функцію перейменування.

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

fs.rename (oldPath, newPath, зворотний виклик)

Додано в: v0.0.2

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

Асинхронне перейменування (2). Аргументи, окрім можливого винятку, для зворотного виклику завершення не надаються.


5
Для тих, хто цікавиться, куди пішов коментар @ seppo0010: це було на моїй відповіді, яку я видалив і опублікував як коментар до ОП.
Метт Бал

6
Це не спрацює, якщо ви перетинаєте розділи або використовуєте віртуальну файлову систему, яка не підтримує рухомі файли. Ви краще скористайтеся цим рішенням із резервним копієм
Flavien Volken

У 3-й відповіді "Хані" є приклад коду!
Натан

47

Цей приклад взятий з: Node.js в дії

Функція move (), яка перейменовується, якщо можливо, або переходить до копіювання

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

3
Працював як шарм. Дякую! Якщо я можу додати трохи: 'move' може бути кращим іменем, коли він від’єднує oldPath.
Джокер

У цьому випадку функція copy () нормальна, але якщо хтось має намір загорнути її в об'єкт Promise, будь ласка, дивіться мою "відповідь" нижче або майте на увазі, щоб вирішити обіцянку після події "закриття" у потоці запису, не в потоці читання.
Джем

Це виглядає як щось, що буде працювати для моїх потреб, проте я не знаю, як використовувати стиль module.exports = function {}. чи я скопіюю цей код у сам додаток, де вже є var fs = requ ('fs'); а потім викликайте fs.move (oldFile, newFile, function (помилка) {....}) замість fs.rename?
Цікаво101

@ Curious101 Ви можете помістити це у такий файл, як filemove.js та імпортувати його як var filemove = requ ('filemove'); потім використовуйте його як filemove (...);
Теоман шипахі

Дякую @Teomanshipahi. У цьому випадку я можу додати до mylibrary.js і використовувати його звідти. Я думав, що це якийсь добре відомий метод додавання методів прототипу, щоб він став доступним в самому об'єкті.
Цікаво101

35

Використання nodejs спочатку

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

(ПРИМІТКА: "Це не спрацює, якщо ви перетинаєте розділи або використовуєте віртуальну файлову систему, яка не підтримує рухомі файли. [...]" - Flavien Volken 2 вересня '15 о 12:50 ")


30

Використовуйте модуль вузла mv, який спочатку спробує виконати fs.renameкопіювання, а потім відкидання, а потім від’єднання.


Добре працював над простими вимогами до переміщення файлу.
arcseldon

1
andrewrk видається автором цього mvмодуля вузла. Мені подобається використовувати npm для встановлення; npm install mv --save-dev; ось посилання npm
The Red Pea

3
Як це залежність від розробників? Чи не потрібен додаток, щоб функціонувати?
jgr0

17

util.pump застаріло у вузлі 0.10 і генерує попереджувальне повідомлення

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

Тож рішенням для копіювання файлів за допомогою потоків є:

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

2
Це правильний спосіб копіювання / переміщення файлу на двох різних розділах. Дякую!
slickplaid

9

Використання функції перейменування:

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

де

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

припускаючи, що ви хочете зберегти ім'я файлу незмінним.


4
Будьте уважні, це не вийде, якщо ви спробуєте перейменувати файл між різними розділами, а також на деяких віртуальних файлових системах (наприклад, докер)
Flavien Volken,

8

fs-extraМодуль дозволяє зробити це з його move()методом. Я вже його реалізував, і він добре працює, якщо ви хочете повністю перемістити файл з однієї директорії в іншу - тобто. видалення файлу з вихідного каталогу. Має працювати в більшості основних випадків.

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

5

Ось приклад використання util.pump, з >> Як перенести файл a до іншого розділу чи пристрою в 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');
});

20
Варто зазначити, що робити це потрібно лише під час переміщення файлів у томах. В іншому випадку ви можете просто використовувати fs.rename()(в томі перейменування файлу та переміщення його - те саме).
s4y

4
util.pump застарілий.
andrewrk


Чи можливо перемістити файл з локальної машини на сервер?
Халк1991

Ні, для цього вам потрібно використовувати щось інше (наприклад, використання FTP, HTTP або іншого протоколу).
alessioalex

4

Використання обіцянок для версій Node понад 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();

3
Просто слово обережності fs.renameне працює, якщо ви перебуваєте в середовищі Докера з обсягами.
Атул Ядав

Додайте asyncдекларацію до moveThemфункції.
H_I

3

Лише мої 2 копійки, як зазначено у відповіді вище : Метод copy () не слід використовувати як є для копіювання файлів без невеликого коригування:

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

Функція копіювання, загорнута у обіцянку:

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

Однак майте на увазі, що файлова система може вийти з ладу, якщо цільова папка не існує.


3

Я хотів би розділити всі залучені функції (тобто rename, copy, unlink) один від одного , щоб отримати гнучкість і promisify все, звичайно:

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 це лише зручність функції, і ми можемо застосовувати функції окремо, коли, наприклад, нам потрібна більш точна обробка винятків.


2

Shelljs - дуже зручне рішення.

команда: mv ([параметри,] джерело, призначення)

Доступні варіанти:

-f: сила (поведінка за замовчуванням)

-n: для запобігання перезапису

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

1

це повторна відповідь теоманових шипахі з дещо менш неоднозначною назвою та слідування дизайнерському принципу визначення коду, перш ніж ви намагаєтесь його зателефонувати. (Хоча вузол дозволяє робити інакше, не дуже добре ставити візок перед конем.)

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

0

За допомогою наведеної нижче URL-адреси ви можете скопіювати або перемістити свій файл ТОЧНИЙ Джерело до цільового джерела

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 *********/



-6

Ви можете використовувати move-fileпакет npm:

Спочатку встановіть пакет:

$ npm install move-file

Використання:

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

Коротка та розумна відповідь, Добре @paridhishah
Abdullah Pariyani

2
Це заклик до функції, яка ще не створена, тому просто призведе до помилки.
Стів Кері
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.