本章の内容
この本の焦点はシェルスクリプティングであるため、テキストデータのみを扱います。
fs.fchmodSync(fd, mode)
fs.fchownSync(fd, uid, gid)
fs.fdatasyncSync(fd)
fs.fstatSync(fd, options?)
fs.fsyncSync(fd)
fs.ftruncateSync(fd, len?)
fs.futimesSync(fd, atime, mtime)
fileHandle.close()
fileHandle.chmod(mode)
fileHandle.chown(uid, gid)
本章では(3)を使用しません。(1)と(2)で十分です。
名前が「l」で始まる関数は、通常、シンボリックリンクを操作します。
名前が「f」で始まる関数は、通常、ファイル記述子を管理します。
いくつかのクラスがNode.jsのファイルシステムAPIで重要な役割を果たします。
Node.js関数が文字列(A行)でファイルシステムパスを受け入れる場合、通常は`URL`のインスタンス(B行)も受け入れます。
.equal(
assert.readFileSync(
fs'/tmp/text-file.txt', {encoding: 'utf-8'}), // (A)
'Text content'
;
).equal(
assert.readFileSync(
fsnew URL('file:///tmp/text-file.txt'), {encoding: 'utf-8'}), // (B)
'Text content'
; )
パスと`file:` URL間の変換は簡単そうに見えますが、驚くほど多くの落とし穴があります:パーセントエンコーディングまたはデコーディング、Windowsドライブ文字など。代わりに、次の2つの関数を使用することをお勧めします。
本章ではファイルURLを使用しません。それらのユースケースについては、§7.11.1 「クラス`URL`」で説明しています。
クラス`Buffer`は、Node.js上の固定長のバイトシーケンスを表します。これは`Uint8Array`(TypedArray)のサブクラスです。バッファは主にバイナリファイルの操作に使用されるため、この本ではあまり関心がありません。
Node.jsがBufferを受け入れる場合、Uint8Arrayも受け入れます。したがって、Uint8Arrayはクロスプラットフォームで、Bufferはクロスプラットフォームではないため、前者の方が優れています。
バッファは、Uint8Arrayではできないことを1つ実行できます。さまざまなエンコーディングでのテキストのエンコードとデコードです。Uint8ArrayでUTF-8をエンコードまたはデコードする必要がある場合は、クラス`TextEncoder`またはクラス`TextDecoder`を使用できます。これらのクラスは、ほとんどのJavaScriptプラットフォームで使用できます。
> new TextEncoder().encode('café')Uint8Array.of(99, 97, 102, 195, 169)
> new TextDecoder().decode(Uint8Array.of(99, 97, 102, 195, 169))'café'
一部の関数は、ネイティブのNode.jsストリームを受け入れますまたは返します。
ネイティブストリームの代わりに、Node.jsでクロスプラットフォームの*Webストリーム*を使用できるようになりました。§10 「Node.jsでのWebストリームの使用」で説明されています。
`fs.readFileSync(filePath, options?)`は、`filePath`のファイルを単一の文字列に読み込みます。
.equal(
assert.readFileSync('text-file.txt', {encoding: 'utf-8'}),
fs'there\r\nare\nmultiple\nlines'
; )
このアプローチの長所と短所(ストリームを使用する場合と比較)
次に、読み込んだ文字列を行に分割する方法を見ていきます。
次のコードは、改行文字を削除しながら文字列を行に分割します。UnixとWindowsの改行文字で動作します。
const RE_SPLIT_EOL = /\r?\n/;
function splitLines(str) {
return str.split(RE_SPLIT_EOL);
}.deepEqual(
assertsplitLines('there\r\nare\nmultiple\nlines'),
'there', 'are', 'multiple', 'lines']
[; )
「EOL」は「行末」を表します。Unixの改行文字(`'\n'`)とWindowsの改行文字(`'\r\n'`、前の例のように最初のもの)の両方を許可します。詳細については、§8.3 「プラットフォーム間での改行文字の処理」を参照してください。
次のコードは、改行文字を含めて文字列を行に分割します。UnixとWindowsの改行文字で動作します(「EOL」は「行末」を表します)。
const RE_SPLIT_AFTER_EOL = /(?<=\r?\n)/; // (A)
function splitLinesWithEols(str) {
return str.split(RE_SPLIT_AFTER_EOL);
}
.deepEqual(
assertsplitLinesWithEols('there\r\nare\nmultiple\nlines'),
'there\r\n', 'are\n', 'multiple\n', 'lines']
[;
).deepEqual(
assertsplitLinesWithEols('first\n\nthird'),
'first\n', '\n', 'third']
[;
).deepEqual(
assertsplitLinesWithEols('EOL at the end\n'),
'EOL at the end\n']
[;
).deepEqual(
assertsplitLinesWithEols(''),
'']
[; )
A行には、後方参照アサーションを含む正規表現が含まれています。`\r?\n`のパターンに先行される場所で一致しますが、何もキャプチャしません。そのため、入力文字列が分割される文字列フラグメントの間で何も削除されません。
後方参照アサーションをサポートしていないエンジン(この表を参照)では、次の解決策を使用できます。
function splitLinesWithEols(str) {
if (str.length === 0) return [''];
const lines = [];
let prevEnd = 0;
while (prevEnd < str.length) {
// Searching for '\n' means we’ll also find '\r\n'
const newlineIndex = str.indexOf('\n', prevEnd);
// If there is a newline, it’s included in the line
const end = newlineIndex < 0 ? str.length : newlineIndex+1;
.push(str.slice(prevEnd, end));
lines= end;
prevEnd
}return lines;
}
この解決策はシンプルですが、冗長です。
`splitLinesWithEols()`の両方のバージョンで、再びUnixの改行文字(`'\n'`)とWindowsの改行文字(`'\r\n'`)の両方を許可します。詳細については、§8.3 「プラットフォーム間での改行文字の処理」を参照してください。
ストリームを使用してテキストファイルを読み込むこともできます。
import {Readable} from 'node:stream';
const nodeReadable = fs.createReadStream(
'text-file.txt', {encoding: 'utf-8'});
const webReadableStream = Readable.toWeb(nodeReadable);
const lineStream = webReadableStream.pipeThrough(
new ChunksToLinesStream());
for await (const line of lineStream) {
console.log(line);
}
// Output:
// 'there\r\n'
// 'are\n'
// 'multiple\n'
// 'lines'
次の外部機能を使用しました。
Webストリームは非同期的に反復可能であるため、`for-await-of`ループを使用して行を反復処理できます。
テキスト行に関心がない場合は、`ChunksToLinesStream`は必要なく、`webReadableStream`を反復処理して、任意の長さのチャンクを取得できます。
詳細情報
Webストリームについては、§10 「Node.jsでのWebストリームの使用」を参照してください。
改行文字については、§8.3 「プラットフォーム間での改行文字の処理」を参照してください。
このアプローチの長所と短所(単一の文字列を読み込む場合と比較)
`fs.writeFileSync(filePath, str, options?)`は、`filePath`のファイルに`str`を書き込みます。そのパスにファイルが既に存在する場合は、上書きされます。
次のコードは、この関数の使用方法を示しています。
.writeFileSync(
fs'new-file.txt',
'First line\nSecond line\n',
encoding: 'utf-8'}
{; )
改行文字の詳細については、§8.3 「プラットフォーム間での改行文字の処理」を参照してください。
長所と短所(ストリームを使用する場合と比較)
次のコードは、既存のファイルにテキスト行を追加します。
.appendFileSync(
fs'existing-file.txt',
'Appended line\n',
encoding: 'utf-8'}
{; )
このタスクを実行するには、fs.writeFileSync()
も使用できます。
.writeFileSync(
fs'existing-file.txt',
'Appended line\n',
encoding: 'utf-8', flag: 'a'}
{; )
このコードは、既存の内容を上書きするために使用したものとほぼ同じです(詳細については前のセクションを参照してください)。唯一の違いは、.flag
オプションを追加したことだけです。値'a'
はデータを追記することを意味します。ファイルが存在しない場合にエラーをスローするなど、他の可能な値については、Node.js のドキュメントを参照してください。
注意:一部の関数ではこのオプションは.flag
と呼ばれ、他の関数では.flags
と呼ばれます。
次のコードは、ストリームを使用して複数の文字列をファイルに書き込みます。
import {Writable} from 'node:stream';
const nodeWritable = fs.createWriteStream(
'new-file.txt', {encoding: 'utf-8'});
const webWritableStream = Writable.toWeb(nodeWritable);
const writer = webWritableStream.getWriter();
try {
await writer.write('First line\n');
await writer.write('Second line\n');
await writer.close();
finally {
} .releaseLock()
writer }
次の関数を使用しました。
fs.createWriteStream(path, options?)
は、Node.js ストリーム(stream.Writable
のインスタンス)を作成します。stream.Writable.toWeb(streamWritable)
は、書き込み可能な Node.js ストリームをWeb ストリーム(WritableStream
のインスタンス)に変換します。詳細情報
長所と短所(単一文字列の書き込みと比較)
次のコードは、ストリームを使用して既存のファイルにテキストを追加します。
import {Writable} from 'node:stream';
const nodeWritable = fs.createWriteStream(
'existing-file.txt', {encoding: 'utf-8', flags: 'a'});
const webWritableStream = Writable.toWeb(nodeWritable);
const writer = webWritableStream.getWriter();
try {
await writer.write('First appended line\n');
await writer.write('Second appended line\n');
await writer.close();
finally {
} .releaseLock()
writer }
このコードは、既存の内容を上書きするために使用したものとほぼ同じです(詳細については前のセクションを参照してください)。唯一の違いは、.flags
オプションを追加したことだけです。値'a'
はデータを追記することを意味します。ファイルが存在しない場合にエラーをスローするなど、他の可能な値については、Node.js のドキュメントを参照してください。
注意:一部の関数ではこのオプションは.flag
と呼ばれ、他の関数では.flags
と呼ばれます。
残念ながら、すべてのプラットフォームが改行(EOL)を示す改行文字を同じように使用しているわけではありません。
'\r\n'
です。'\n'
です。すべてのプラットフォームで動作するような方法でEOLを処理するには、いくつかの戦略があります。
テキストを読み取るときは、両方のEOLを認識することが最善です。
テキストを行に分割する場合、どのようなものになるでしょうか?EOL(いずれかの形式)を末尾に含めることができます。これにより、これらの行を変更してファイルに書き込む場合でも、変更する必要を最小限に抑えることができます。
EOL付きの行を処理する際には、それらを削除することが役立つ場合があります。たとえば、次の関数を使用します。
const RE_EOL_REMOVE = /\r?\n$/;
function removeEol(line) {
const match = RE_EOL_REMOVE.exec(line);
if (!match) return line;
return line.slice(0, match.index);
}
.equal(
assertremoveEol('Windows EOL\r\n'),
'Windows EOL'
;
).equal(
assertremoveEol('Unix EOL\n'),
'Unix EOL'
;
).equal(
assertremoveEol('No EOL'),
'No EOL'
; )
改行文字の書き込みに関しては、2つのオプションがあります。
'node:os'
内の定数EOL
には、現在のプラットフォームのEOLが含まれています。次の関数は、ディレクトリをトラバースし、そのすべての後続要素(子、子の子など)を一覧表示します。
import * as path from 'node:path';
function* traverseDirectory(dirPath) {
const dirEntries = fs.readdirSync(dirPath, {withFileTypes: true});
// Sort the entries to keep things more deterministic
.sort(
dirEntries, b) => a.name.localeCompare(b.name, 'en')
(a;
)for (const dirEntry of dirEntries) {
const fileName = dirEntry.name;
const pathName = path.join(dirPath, fileName);
yield pathName;
if (dirEntry.isDirectory()) {
yield* traverseDirectory(pathName);
}
} }
この機能を使用しました。
fs.readdirSync(thePath, options?)
は、thePath
にあるディレクトリの子供を返します。.withFileTypes
がtrue
の場合、関数はfs.Dirent
のインスタンスであるディレクトリエントリを返します。これらには、次のようなプロパティがあります。dirent.name
dirent.isDirectory()
dirent.isFile()
dirent.isSymbolicLink()
.withFileTypes
がfalse
であるか、存在しない場合、関数はファイル名を含む文字列を返します。次のコードは、traverseDirectory()
の動作を示しています。
for (const filePath of traverseDirectory('dir')) {
console.log(filePath);
}
// Output:
// 'dir/dir-file.txt'
// 'dir/subdir'
// 'dir/subdir/subdir-file1.txt'
// 'dir/subdir/subdir-file2.csv'
mkdir
、mkdir -p
)ディレクトリを作成するには、次の関数を使用できます。
.mkdirSync(thePath, options?): undefined | string fs
options.recursive
は、関数がthePath
にディレクトリを作成する方法を決定します。
.recursive
が存在しないかfalse
の場合、mkdirSync()
はundefined
を返し、次の場合に例外がスローされます。thePath
にディレクトリ(またはファイル)が既に存在する。thePath
の親ディレクトリが存在しない。.recursive
がtrue
の場合thePath
にディレクトリが既に存在していても問題ありません。thePath
の先祖ディレクトリが必要に応じて作成されます。mkdirSync()
は、最初に新しく作成されたディレクトリのパスを返します。これはmkdirSync()
の動作です。
.deepEqual(
assertArray.from(traverseDirectory('.')),
['dir',
];
).mkdirSync('dir/sub/subsub', {recursive: true});
fs.deepEqual(
assertArray.from(traverseDirectory('.')),
['dir',
'dir/sub',
'dir/sub/subsub',
]; )
関数traverseDirectory(dirPath)
は、dirPath
にあるディレクトリのすべての後続要素を一覧表示します。
必要に応じてネストされたファイル構造を設定する場合、新しいファイルを作成するときに、先祖ディレクトリが存在することを常に確認することはできません。そこで、次の関数が役立ちます。
import * as path from 'node:path';
function ensureParentDirectory(filePath) {
const parentDir = path.dirname(filePath);
if (!fs.existsSync(parentDir)) {
.mkdirSync(parentDir, {recursive: true});
fs
} }
ここで、ensureParentDirectory()
の動作を確認できます(A行)。
.deepEqual(
assertArray.from(traverseDirectory('.')),
['dir',
];
)const filePath = 'dir/sub/subsub/new-file.txt';
ensureParentDirectory(filePath); // (A)
.writeFileSync(filePath, 'content', {encoding: 'utf-8'});
fs.deepEqual(
assertArray.from(traverseDirectory('.')),
['dir',
'dir/sub',
'dir/sub/subsub',
'dir/sub/subsub/new-file.txt',
]; )
fs.mkdtempSync(pathPrefix, options?)
は一時ディレクトリを作成します。pathPrefix
に6文字のランダムな文字を追加し、新しいパスにディレクトリを作成して、そのパスを返します。
一部のプラットフォームでは、末尾のXをランダムな文字に置き換えるため、pathPrefix
は大文字の「X」で終わらないようにしてください。
オペレーティングシステム固有のグローバル一時ディレクトリ内に一時ディレクトリを作成する場合は、関数os.tmpdir()
を使用できます。
import * as os from 'node:os';
import * as path from 'node:path';
const pathPrefix = path.resolve(os.tmpdir(), 'my-app');
// e.g. '/var/folders/ph/sz0384m11vxf/T/my-app'
const tmpPath = fs.mkdtempSync(pathPrefix);
// e.g. '/var/folders/ph/sz0384m11vxf/T/my-app1QXOXP'
一時ディレクトリは、Node.js スクリプトが終了しても自動的に削除されないことに注意することが重要です。自分で削除するか、オペレーティングシステムがグローバル一時ディレクトリを定期的にクリーンアップする(するかどうかは別として)ことに依存する必要があります。
fs.cpSync(srcPath, destPath, options?)
:ファイルまたはディレクトリをsrcPath
からdestPath
にコピーします。興味深いオプション。
.recursive
(デフォルト:false
):このオプションがtrue
の場合のみ、ディレクトリ(空のディレクトリを含む)がコピーされます。.force
(デフォルト:true
):true
の場合、既存のファイルは上書きされます。false
の場合、既存のファイルは保持されます。.errorOnExist
をtrue
に設定すると、ファイルパスの競合が発生した場合にエラーがスローされます。.filter
は、コピーするファイルを制御できる関数です。.preserveTimestamps
(デフォルト:false
):true
の場合、destPath
のコピーは、srcPath
のオリジナルと同じタイムスタンプを取得します。これは動作中の関数です。
.deepEqual(
assertArray.from(traverseDirectory('.')),
['dir-orig',
'dir-orig/some-file.txt',
];
).cpSync('dir-orig', 'dir-copy', {recursive: true});
fs.deepEqual(
assertArray.from(traverseDirectory('.')),
['dir-copy',
'dir-copy/some-file.txt',
'dir-orig',
'dir-orig/some-file.txt',
]; )
関数traverseDirectory(dirPath)
は、dirPath
にあるディレクトリのすべての後続要素を一覧表示します。
fs.renameSync(oldPath, newPath)
は、ファイルまたはディレクトリの名前をoldPath
からnewPath
に変更するか、移動します。
この関数を使用して、ディレクトリの名前を変更しましょう。
.deepEqual(
assertArray.from(traverseDirectory('.')),
['old-dir-name',
'old-dir-name/some-file.txt',
];
).renameSync('old-dir-name', 'new-dir-name');
fs.deepEqual(
assertArray.from(traverseDirectory('.')),
['new-dir-name',
'new-dir-name/some-file.txt',
]; )
ここでは、この関数を使用してファイルを移動します。
.deepEqual(
assertArray.from(traverseDirectory('.')),
['dir',
'dir/subdir',
'dir/subdir/some-file.txt',
];
).renameSync('dir/subdir/some-file.txt', 'some-file.txt');
fs.deepEqual(
assertArray.from(traverseDirectory('.')),
['dir',
'dir/subdir',
'some-file.txt',
]; )
関数traverseDirectory(dirPath)
は、dirPath
にあるディレクトリのすべての後続要素を一覧表示します。
rm
、rm -r
)fs.rmSync(thePath, options?)
は、thePath
にあるファイルまたはディレクトリを削除します。興味深いオプション。
.recursive
(デフォルト:false
):このオプションがtrue
の場合のみ、ディレクトリ(空のディレクトリを含む)が削除されます。.force
(デフォルト:false
):false
の場合、thePath
にファイルまたはディレクトリが存在しない場合、例外がスローされます。fs.rmSync()
を使用してファイルを削除してみましょう。
.deepEqual(
assertArray.from(traverseDirectory('.')),
['dir',
'dir/some-file.txt',
];
).rmSync('dir/some-file.txt');
fs.deepEqual(
assertArray.from(traverseDirectory('.')),
['dir',
]; )
ここでは、fs.rmSync()
を使用して、空ではないディレクトリを再帰的に削除します。
.deepEqual(
assertArray.from(traverseDirectory('.')),
['dir',
'dir/subdir',
'dir/subdir/some-file.txt',
];
).rmSync('dir/subdir', {recursive: true});
fs.deepEqual(
assertArray.from(traverseDirectory('.')),
['dir',
]; )
関数traverseDirectory(dirPath)
は、dirPath
にあるディレクトリのすべての後続要素を一覧表示します。
rmdir
)fs.rmdirSync(thePath, options?)
は、空のディレクトリを削除します(ディレクトリが空でない場合は例外がスローされます)。
次のコードは、この関数の動作を示しています。
.deepEqual(
assertArray.from(traverseDirectory('.')),
['dir',
'dir/subdir',
];
).rmdirSync('dir/subdir');
fs.deepEqual(
assertArray.from(traverseDirectory('.')),
['dir',
]; )
関数traverseDirectory(dirPath)
は、dirPath
にあるディレクトリのすべての後続要素を一覧表示します。
ディレクトリdir
に出力を保存するスクリプトは、開始前にdir
をクリアする必要があることがよくあります。つまり、dir
内のすべてのファイルを削除して空にするということです。次の関数はそれを行います。
import * as path from 'node:path';
function clearDirectory(dirPath) {
for (const fileName of fs.readdirSync(dirPath)) {
const pathName = path.join(dirPath, fileName);
.rmSync(pathName, {recursive: true});
fs
} }
2つのファイルシステム関数を使用しました。
fs.readdirSync(dirPath)
は、dirPath
にあるディレクトリのすべての子の名前を返します。§8.4.1「ディレクトリのトラバース」で説明されています。fs.rmSync(pathName, options?)
は、ファイルとディレクトリ(空ではないディレクトリを含む)を削除します。§8.6.1「ファイルと任意のディレクトリの削除(シェル:rm
、rm -r
)」で説明されています。これはclearDirectory()
の使用例です。
.deepEqual(
assertArray.from(traverseDirectory('.')),
['dir',
'dir/dir-file.txt',
'dir/subdir',
'dir/subdir/subdir-file.txt'
];
)clearDirectory('dir');
.deepEqual(
assertArray.from(traverseDirectory('.')),
['dir',
]; )
ライブラリtrash
は、ファイルとフォルダーをゴミ箱に移動します。macOS、Windows、Linux で動作します(Linux ではサポートが限られており、ヘルプが必要とされています)。これは、READMEファイルからの例です。
import trash from 'trash';
await trash(['*.png', '!rainbow.png']);
trash()
は、最初の引数として文字列の配列または文字列を受け入れます。任意の文字列はglobパターン(アスタリスクやその他のメタ文字を含む)にすることができます。
fs.existsSync(thePath)
は、thePath
にファイルまたはディレクトリが存在する場合にtrue
を返します。
.deepEqual(
assertArray.from(traverseDirectory('.')),
['dir',
'dir/some-file.txt',
];
).equal(
assert.existsSync('dir'), true
fs;
).equal(
assert.existsSync('dir/some-file.txt'), true
fs;
).equal(
assert.existsSync('dir/non-existent-file.txt'), false
fs; )
関数traverseDirectory(dirPath)
は、dirPath
にあるディレクトリのすべての後続要素を一覧表示します。
fs.statSync(thePath, options?)
は、thePath
にあるファイルまたはディレクトリに関する情報を含むfs.Stats
のインスタンスを返します。
興味深いoptions
.throwIfNoEntry
(デフォルト:true
):path
にエンティティがない場合に何が起こりますか?true
の場合、例外がスローされます。false
の場合、undefined
が返されます。.bigint
(デフォルト:false
):true
の場合、この関数は数値(タイムスタンプなど、下記参照)にbigintを使用します。fs.Stats
のインスタンスのプロパティ
stats.isFile()
stats.isDirectory()
stats.isSymbolicLink()
stats.size
はバイト単位のサイズです。stats.atime
:前回のアクセス時間stats.mtime
:前回の変更時間stats.birthtime
:作成時間atime
stats.atime
:Date
のインスタンスstats.atimeMS
:POSIX エポックからのミリ秒stats.atimeNs
:POSIX エポックからのナノ秒(オプション.bigint
が必要)次の例では、fs.statSync()
を使用して関数isDirectory()
を実装します。
function isDirectory(thePath) {
const stats = fs.statSync(thePath, {throwIfNoEntry: false});
return stats !== undefined && stats.isDirectory();
}
.deepEqual(
assertArray.from(traverseDirectory('.')),
['dir',
'dir/some-file.txt',
];
)
.equal(
assertisDirectory('dir'), true
;
).equal(
assertisDirectory('dir/some-file.txt'), false
;
).equal(
assertisDirectory('non-existent-dir'), false
; )
関数traverseDirectory(dirPath)
は、dirPath
にあるディレクトリのすべての後続要素を一覧表示します。
ファイル属性を変更するための関数について簡単に見てみましょう。
fs.chmodSync(path, mode)
は、ファイルの権限を変更します。fs.chownSync(path, uid, gid)
は、ファイルの所有者とグループを変更します。fs.utimesSync(path, atime, mtime)
は、ファイルのタイムスタンプを変更します。atime
:前回のアクセス時間mtime
:前回の変更時間ハードリンクを操作するための関数
fs.linkSync(existingPath, newPath)
はハードリンクを作成します。fs.unlinkSync(path)
はハードリンクを削除し、それがそのファイルへの最後のハードリンクである場合、そのファイルを削除する可能性があります。シンボリックリンクを操作するための関数
fs.symlinkSync(target, path, type?)
は、path
からtarget
へのシンボリックリンクを作成します。fs.readlinkSync(path, options?)
は、path
にあるシンボリックリンクのターゲットを返します。次の関数は、シンボリックリンクを逆参照せずに操作します(名前プレフィックス「l」に注意してください)。
fs.lchmodSync(path, mode)
は、path
にあるシンボリックリンクの権限を変更します。fs.lchownSync(path, uid, gid)
は、path
で指定されたシンボリックリンクの所有者ユーザーとグループを変更します。fs.lutimesSync(path, atime, mtime)
は、path
で指定されたシンボリックリンクのタイムスタンプを変更します。fs.lstatSync(path, options?)
は、path
で指定されたシンボリックリンクの統計情報(タイムスタンプなど)を返します。その他の便利な関数
fs.realpathSync(path, options?)
は、ドット(.
)、ダブルドット(..
)、およびシンボリックリンクを解決することで、正規化されたパス名を求めます。シンボリックリンクの処理方法に影響を与える関数のオプション
fs.cpSync(src, dest, options?)
:
.dereference
(デフォルト: false
):true
の場合、シンボリックリンク自体ではなく、シンボリックリンクが指すファイルをコピーします。.verbatimSymlinks
(デフォルト: false
):false
の場合、コピーされたシンボリックリンクのターゲットは、同じ場所に指し続けるように更新されます。true
の場合、ターゲットは変更されません。