情報アイランド

「情報を制する者は世界を制す」をモットーに様々な情報を提供することを目指すブログです。現在はプログラミング関連情報が多めですが、投資関連情報も取り扱っていきたいです。

Node.jsでフォルダを再帰的にコピーする

フォルダを再帰的にコピーするには非同期的にコピーする方法と同期的にコピーする方法の2つがあります。

非同期的なコピー

フォルダを非同期的に再帰的にコピーするにはncpモジュールのncp.ncp関数やfs-extraモジュールのfsExtra.copy関数を使用します。

var ncp = require('ncp');

ncp.ncp('xxx', 'yyy', {
    clobber: true, 
    dereference: false, 
    filter: function (element) {
        return true;
        //or
        return false;
    }, 
    transform: function (readable, writable) {
        readable.pipe(writable);
    }, 
    stopOnErr: false, 
    errs: writable
}, function (err) {
});
var fsExtra = require('fs-extra');

fsExtra.copy('xxx', 'yyy', {
    clobber: true, 
    dereference: false, 
    filter: function (element) {
        return true;
        //or
        return false;
    }, 
    preserveTimestamps: false 
}, function (err) {
});

第1引数にコピー元のフォルダのパスを指定します。

第2引数にコピー先のフォルダのパスを指定します。

第3引数にオプションをオブジェクトとして指定します。この引数は指定しなくても構いません。

ncp.ncp関数とfsExtra.copy関数に共通するオプションには下のようなものがあります。

  • clobber・・・ファイルが既に存在する場合に上書きするかを真偽値として指定します。デフォルトはtrueです。
  • dereference・・・シンボリックリンクをコピーする場合にシンボリックリンクの参照先のファイルをコピーするか、シンボリックリンクそのものをコピーするかを真偽値として指定します。シンボリックリンクの参照先のファイルをコピーする場合にはtrueを指定し、シンボリックリンクそのものをコピーする場合にはfalseを指定します。デフォルトはfalseです。
  • filter・・・ファイルやフォルダのフィルタ条件を関数として指定します。この関数の第1引数はncp.ncp関数の場合にはコピー先のファイルやフォルダのパスであり、fsExtra.copy関数の場合にはコピー元のファイルやフォルダのパスです。この関数では返り値としてファイルやフォルダがフィルタ条件を満たしているかを真偽値として返すようにします。フォルダがフィルタされた場合にはそのフォルダの配下のファイルやフォルダがコピーされることはありませんので注意してください。

ncp.ncp関数独自のオプションには下のようなものがあります。

  • transform・・・ファイルのデータを変換する処理を関数として指定します。このオプションに関しては下の記事を参照してください。
  • stopOnErr・・・エラー発生時にコピーを中断するかを真偽値として指定します。falseである場合にはエラー発生時にerrsオプションのストリームにエラーオブジェクトが書き込まれます。デフォルトはfalseです。
  • errs・・・エラー発生時にエラーオブジェクトが書き込まれる書き込みストリームを指定します。

fsExtra.copy関数独自のオプションには下のようなものがあります。

  • preserveTimestamps・・・コピー先のファイルの更新日時やアクセス日時をコピー元のファイルの更新日時やアクセス日時に変更するかを真偽値として指定します。デフォルトはfalseです。

第4引数にコールバック関数を指定します。この関数の第1引数はエラーオブジェクトです。

同期的なコピー

フォルダを同期的に再帰的にコピーするにはfs-extraモジュールのfsExtra.copySync関数を使用します。

fsExtra.copySync('xxx', 'yyy', {
    clobber: true, 
    dereference: false, 
    filter: function (element) {
        return true;
        //or
        return false;
    }, 
    preserveTimestamps: false 
});

第1引数にコピー元のフォルダのパスを指定します。

第2引数にコピー先のフォルダのパスを指定します。

第3引数にオプションをオブジェクトとして指定します。この引数は指定しなくても構いません。このオプションはfsExtra.copy関数の第3引数のオプションと同じです。

使い分け

原則的にはncp.ncp関数やfsExtra.copy関数を使用するべきであり、特に理由がないならfsExtra.copySync関数は使用するべきではありません。

これは、ファイルやフォルダへのアクセスは非常に時間の掛かる処理であるためです。ファイルやフォルダへのアクセスを同期的に行うとアクセスが完了するまでプログラムは待機状態となり、他の処理を行うことができません。長い時間プログラムが待機状態になると様々な問題を引き起こす可能性があります(このような現象をスターベーションと言います)。

サンプルコード1

ncp.ncp関数の使用例です。

3つ目のコマンドライン引数として与えられたフォルダを4つ目のコマンドライン引数として与えられたフォルダに非同期的に再帰的にコピーします。

ncp.js

var ncp = require('ncp');

ncp.ncp(process.argv[2], process.argv[3], {}, function (err) {
    if (err) {
        console.error(err);
        process.exit(1);
    }
    else {
        console.log('finished!!');
    }
});

使用パッケージ

  • ncp
    npm install ncpでインストールします。

実行結果

現在のフォルダにはfolderという名称のフォルダが存在しており、textfile.txtという名称のファイルとfolder2という名称のフォルダを含んでいます。また、folder2フォルダはtextfile2.txtという名称のファイルを含んでいます。

C:\work\node>dir folder
 Volume in drive C is TI31035600A
 Volume Serial Number is 1CBD-3C48

 Directory of C:\work\node\folder

2016/11/19  09:09    <DIR>          .
2016/11/19  09:09    <DIR>          ..
2016/11/19  09:09    <DIR>          folder2
2016/11/19  09:09                 4 textfile.txt
               1 File(s)              4 bytes
               3 Dir(s)  26,537,566,208 bytes free

C:\work\node>dir folder\folder2
 Volume in drive C is TI31035600A
 Volume Serial Number is 1CBD-3C48

 Directory of C:\work\node\folder\folder2

2016/11/19  09:09    <DIR>          .
2016/11/19  09:09    <DIR>          ..
2016/11/19  09:09                 4 textfile2.txt
               1 File(s)              4 bytes
               2 Dir(s)  26,537,566,208 bytes free

folderを3つ目のコマンドライン引数に指定し、folder3を4つ目のコマンドライン引数に指定してコードを実行すると正しくフォルダが再帰的にコピーされます。

C:\work\node>node ncp.js folder folder3
finished!!

C:\work\node>dir folder3
 Volume in drive C is TI31035600A
 Volume Serial Number is 1CBD-3C48

 Directory of C:\work\node\folder3

2016/11/19  09:14    <DIR>          .
2016/11/19  09:14    <DIR>          ..
2016/11/19  09:14    <DIR>          folder2
2016/11/19  09:14                 4 textfile.txt
               1 File(s)              4 bytes
               3 Dir(s)  26,537,607,168 bytes free

C:\work\node>dir folder3\folder2
 Volume in drive C is TI31035600A
 Volume Serial Number is 1CBD-3C48

 Directory of C:\work\node\folder3\folder2

2016/11/19  09:14    <DIR>          .
2016/11/19  09:14    <DIR>          ..
2016/11/19  09:14                 4 textfile2.txt
               1 File(s)              4 bytes
               2 Dir(s)  26,537,607,168 bytes free

関連

pizyumi
プログラミング歴19年のベテランプログラマー。業務システム全般何でも作れます。現在はWeb系の技術を勉強中。
スポンサーリンク

-Node.js