Node.jsでフォルダを再帰的にコピーする:ベストプラクティスとトラブルシューティング
Node.js でフォルダーを再帰的にコピーする方法
fs モジュールとコールバックを使用する
Node.js の標準モジュールである fs
を使用して、フォルダーを再帰的にコピーすることができます。ただし、この方法は非同期処理のため、コールバックを使用して処理の完了を知らせる必要があります。
const fs = require('fs');
function copyFolder(source, dest, callback) {
fs.mkdir(dest, { recursive: true }, (err) => {
if (err) return callback(err);
fs.readdir(source, (err, files) => {
if (err) return callback(err);
files.forEach((file) => {
const srcPath = `${source}/${file}`;
const destPath = `${dest}/${file}`;
fs.stat(srcPath, (err, stats) => {
if (err) return callback(err);
if (stats.isDirectory()) {
copyFolder(srcPath, destPath, callback);
} else {
fs.copyFile(srcPath, destPath, callback);
}
});
});
});
});
}
copyFolder('source', 'dest', (err) => {
if (err) console.error(err);
else console.log('コピー完了');
});
fs-extra モジュールを使用する
fs-extra
は、fs
モジュールを拡張したサードパーティ製モジュールです。fs-extra
を使用すると、copy
関数を使用してフォルダーを再帰的にコピーすることができます。この関数は Promise を返すため、非同期処理をより簡単に処理できます。
const fsExtra = require('fs-extra');
(async () => {
try {
await fsExtra.copy('source', 'dest');
console.log('コピー完了');
} catch (err) {
console.error(err);
}
})();
補足
- 上記のコード例はあくまでも基本的な例です。実際の使用状況に応じて、エラー処理やオプション設定などを追加する必要があります。
- フォルダーをコピーする前に、宛先フォルダーが存在しないことを確認する必要があります。
- ファイルの権限や所有権もコピーされます。
- シンボリックリンクはコピーされません。
const fs = require('fs');
function copyFolder(source, dest, callback) {
fs.mkdir(dest, { recursive: true }, (err) => {
if (err) return callback(err);
fs.readdir(source, (err, files) => {
if (err) return callback(err);
files.forEach((file) => {
const srcPath = `${source}/${file}`;
const destPath = `${dest}/${file}`;
fs.stat(srcPath, (err, stats) => {
if (err) return callback(err);
if (stats.isDirectory()) {
copyFolder(srcPath, destPath, callback);
} else {
fs.copyFile(srcPath, destPath, callback);
}
});
});
});
});
}
copyFolder('source', 'dest', (err) => {
if (err) console.error(err);
else console.log('コピー完了');
});
説明
fs
モジュールをrequire
します。copyFolder
関数を作成します。この関数は、ソースフォルダーと宛先フォルダー、および処理完了時に呼び出されるコールバック関数を引数として受け取ります。fs.mkdir
関数を使用して、宛先フォルダーが存在しない場合は作成します。fs.readdir
関数を使用して、ソースフォルダー内のファイルをすべて読み取ります。- 各ファイルに対して、次の処理を行います。
fs.stat
関数を使用して、ファイルのステータスを取得します。- ファイルがディレクトリの場合は、
copyFolder
関数を使用して再帰的にコピーします。 - ファイルの場合は、
fs.copyFile
関数を使用してファイルをコピーします。
- すべての処理が完了したら、コールバック関数を呼び出します。
使い方
このコードを使用するには、以下の手順を実行します。
- コードを保存します。
- ターミナルを開き、コードのあるディレクトリに移動します。
- 以下のコマンドを実行します。
node index.js
Node.js でフォルダーを再帰的にコピーするその他の方法
Promise を使用する
fs
モジュールの非同期処理を Promise で処理する方法もあります。
const fs = require('fs');
async function copyFolder(source, dest) {
await fs.mkdir(dest, { recursive: true });
const files = await fs.readdir(source);
await Promise.all(files.map(async (file) => {
const srcPath = `${source}/${file}`;
const destPath = `${dest}/${file}`;
const stats = await fs.stat(srcPath);
if (stats.isDirectory()) {
await copyFolder(srcPath, destPath);
} else {
await fs.copyFile(srcPath, destPath);
}
}));
}
copyFolder('source', 'dest')
.then(() => console.log('コピー完了'))
.catch(err => console.error(err));
ロループを使用する
再帰処理を明示的に記述するために、ループを使用する方法もあります。
const fs = require('fs');
function copyFolder(source, dest) {
fs.mkdir(dest, { recursive: true }, (err) => {
if (err) throw err;
const files = fs.readdirSync(source);
for (const file of files) {
const srcPath = `${source}/${file}`;
const destPath = `${dest}/${file}`;
const stats = fs.statSync(srcPath);
if (stats.isDirectory()) {
copyFolder(srcPath, destPath);
} else {
fs.copyFileSync(srcPath, destPath);
}
}
});
}
copyFolder('source', 'dest');
console.log('コピー完了');
サードパーティ製ライブラリを使用する
fs-extra
以外にも、フォルダーのコピーを容易にするサードパーティ製ライブラリがいくつかあります。
これらのライブラリは、それぞれ異なる機能や利点を提供しているため、プロジェクトのニーズに合わせて選択することができます。
選択のヒント
どの方法を選択するかは、プロジェクトの要件と開発者の好みによって異なります。
- コードの簡潔性と読みやすさを重視する場合は、Promise を使用する方が良いでしょう。
- 処理の制御をより細かく行いたい場合は、ループを使用する方法が適しています。
- 既存のライブラリを利用して開発時間を短縮したい場合は、サードパーティ製ライブラリを使用することを検討しましょう。
いずれの方法を選択する場合も、エラー処理とオプション設定を適切に行うことが重要です。
javascript node.js fs