LoginSignup
16
16

More than 5 years have passed since last update.

Node.jsでファイルをコピーする

Posted at

Node.jsで複数のファイルをコピーしたい。

linuxなら

$ cp src/*.html dest

でできるやつだ。

これをNode.jsでやりたい。

なんかライブラリあるだろ、と思ってnpmレポジトリを2分ほど探したが良いのが見つからず。

いや多分よく探せば絶対あるんだけど探すのめんどくさい。

作るか。

ファイルコピーを実装する

まずは一つのファイルをコピーする関数を作る。

fsモジュールの.createReadStream().createWriteStream()を使えば一瞬だ。

var r = fs.createReadStream(src),
    w = fs.createWriteStream(dest);
r.pip(w);

だけどこれだけだとエラーハンドリングとか足らない。

もう少し丁寧にかくとあれだ。

function _copySingle(src, dest, callback) {
    var aborted = false;

    var r = fs.createReadStream(src),
        w = fs.createWriteStream(dest);
    r.on("error", function (err) {
        done(err);
    });
    w.on("error", function (err) {
        done(err);
    });
    w.on("close", function (ex) {
        done();
    });
    r.pipe(w);

    function done(err) {
        if (aborted) {
            return;
        }
        callback(err);
        aborted = true;
    }
}

次にワイルドカードをまとめて処理できるようにする。
こういう時はasyncglobモジュールを使うに限る。限らないけど。


var argx = require('argx'),
    async = require('async'),
    path = require('path'),
    glob = require('glob'),
    mkdirp = require('mkdirp'),
    fs = require('fs');
async.waterfall([
    function (callback) {
        async.concatSeries([].concat(src), glob, callback);
    },
    function (src, callback) {
        _isExistingDir(dest, function (destIsDir) {
            async.each(src, function (src, callback) {
                var srcFilename = path.resolve(src),
                    destFilename = destIsDir ? path.join(dest, path.basename(src)) : path.resolve(dest);
                async.series([
                    function (callback) {
                        if (options.mkdirp) {
                            mkdirp(path.dirname(destFilename), callback);
                        } else {
                            callback(null);
                        }
                    },
                    function (callback) {
                        _copySingle(srcFilename, destFilename, callback);
                    }
                ], callback);
            }, callback);
        });
    }
], callback);

function _isExistingDir(filename, callback) {
    fs.exists(filename, function (exists) {
        if (exists) {
            fs.stat(filename, function (err, stat) {
                callback(!err && stat.isDirectory());
            });
        } else {
            callback(false);
        }
    });
}

npmパッケージにまとめる

あとはパパッとまとめてテスト書いていつも通りnpmパッケージとして公表。
似たようなのいっぱいありそうだけどとりあえず気にしない。

できた。

16
16
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
16