- Node.js
Node.js pathモジュールの使い方|joinとresolveの違い早見表
pathモジュールは、ファイルやフォルダのパス文字列を組み立てたり分解したりするためのNode.js標準モジュールです。よく使う2つの違いは、path.joinが「渡された部品をつなげて整えるだけ」、path.resolveが「右から順にたどって必ず絶対パスを返す」という点にあります。
この記事では、同じ引数をjoinとresolveの両方に渡した出力を14パターン並べ、Windows形式とmacOS・Linux形式の結果もOS別の表にしました。basename・dirname・extname・parse・format・relative・normalize・sepの入出力早見表と、ESMで __dirname の代わりに使う import.meta.dirname(Node.js 20.11以降)と fileURLToPath の両方を、動かした版の結果つきで載せています。出力はすべてNode.js 22.22.2で実際に実行したものです。
pathモジュールの早見表
| やりたいこと | 書き方 | 結果の例 |
|---|---|---|
| 部品をつなげる | path.join('a', 'b', 'c.txt') |
a/b/c.txt |
| 絶対パスにする | path.resolve('a', 'b') |
/home/taro/app/a/b |
| 自分のファイルの場所を基準にする(CommonJS) | path.join(__dirname, 'data', 'a.txt') |
/home/taro/app/data/a.txt |
| 同上(ESM、20.11以降) | path.join(import.meta.dirname, 'data', 'a.txt') |
/home/taro/app/data/a.txt |
| ファイル名を取り出す | path.basename('/a/b/c.txt') |
c.txt |
| 拡張子なしのファイル名 | path.basename('/a/b/c.txt', '.txt') |
c |
| フォルダ部分を取り出す | path.dirname('/a/b/c.txt') |
/a/b |
| 拡張子を取り出す | path.extname('c.tar.gz') |
.gz |
| まとめて分解する | path.parse('/a/b/c.txt') |
{ root, dir, base, ext, name } |
| 部品から組み立てる | path.format({ dir: '/a', name: 'c', ext: '.md' }) |
/a/c.md |
| 相対パスを求める | path.relative('/a/b', '/a/c/d') |
../c/d |
.. や重複した / を整える |
path.normalize('/a//b/../c') |
/a/c |
| 絶対パスか調べる | path.isAbsolute('/a') |
true |
| 区切り文字 | path.sep |
macOS・Linuxは /、Windowsは \ |
| 比べる点 | path.join | path.resolve |
|---|---|---|
| 返す値 | つなげて整えた文字列(相対のままもある) | 必ず絶対パス |
途中に / で始まる引数 |
ただの部品としてつなげる | そこから先をやり直す(左側を捨てる) |
| 現在の作業フォルダ(cwd) | 使わない | 絶対パスにならないときに前へ足す |
| 引数なし・空文字 | . |
cwd |
末尾の / |
残る | 取り除かれる |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Node.js pathモジュールの使い方|joinとresolveの違い早見表」
この記事の確認環境
| 項目 | 内容 |
|---|---|
| 実行した版 | Node.js 22.22.2(Linux x64) |
| 版による違いの確認 | import.meta.dirname は18.20.8 / 20.18.3 / 22.22.2 / 24.21.0で実行 |
| macOS・Linux形式 | Linux上で実行(path と path.posix は同じ結果) |
| Windows形式 | Linux上で path.win32 を使って実行。Windowsの実機での実行は未実行 |
| 仕様の確認 | Node.js公式ドキュメントのPathのページとECMAScript modulesのページを開いて確認 |
path.win32 は、どのOSで動かしてもWindowsと同じ規則で文字列を処理する入口です。cwdを使わない計算(joinやbasenameなど)は実機と同じ結果になります。cwdを使う計算(相対パスのresolve)はcwdの部分だけが実機と異なるため、この記事の表ではその部分を (cwd) と書いています。作業フォルダのパスは /home/taro/app に置き換えています(表示は環境に合わせて置き換えています)。
読み込み方
// CommonJS
const path = require('node:path');
// ESM
import path from 'node:path';
'path' と 'node:path' はどちらも同じモジュールです。node: を付けると、Node.jsの標準モジュールであることがひと目でわかります。
path.joinとpath.resolveの違いを実行結果で比べる
同じ引数を両方に渡した14パターン
次のスクリプトを /home/taro/app をcwdにして実行しました。
const path = require('node:path');
const cases = [
['a', 'b', 'c.txt'],
['/a', 'b'],
['a', '/b'],
['/a', '/b', 'c'],
['a', '../b'],
['a/b', '../../..', 'c'],
['a', '', 'b'],
[''],
[],
['a/', '/b/'],
['a', './b', '.'],
['/a/b', '../c', './d.txt'],
['.', 'a'],
['a//b', 'c/..'],
];
for (const c of cases) {
console.log(JSON.stringify(c), '|', path.join(...c), '|', path.resolve(...c));
}
macOS・Linux形式の実行結果です。
| No. | 引数 | path.join | path.resolve |
|---|---|---|---|
| 1 | 'a', 'b', 'c.txt' |
a/b/c.txt |
/home/taro/app/a/b/c.txt |
| 2 | '/a', 'b' |
/a/b |
/a/b |
| 3 | 'a', '/b' |
a/b |
/b |
| 4 | '/a', '/b', 'c' |
/a/b/c |
/b/c |
| 5 | 'a', '../b' |
b |
/home/taro/app/b |
| 6 | 'a/b', '../../..', 'c' |
../c |
/home/taro/c |
| 7 | 'a', '', 'b' |
a/b |
/home/taro/app/a/b |
| 8 | '' |
. |
/home/taro/app |
| 9 | (引数なし) | . |
/home/taro/app |
| 10 | 'a/', '/b/' |
a/b/ |
/b |
| 11 | 'a', './b', '.' |
a/b |
/home/taro/app/a/b |
| 12 | '/a/b', '../c', './d.txt' |
/a/c/d.txt |
/a/c/d.txt |
| 13 | '.', 'a' |
a |
/home/taro/app/a |
| 14 | 'a//b', 'c/..' |
a/b |
/home/taro/app/a/b |
表から読み取れる5つの決まり
- joinは全部つなげてから整える。 途中の引数が
/で始まっていても部品として扱います(No.3はa/b、No.4は/a/b/c) - resolveは右から左へ読み、絶対パスが現れたらそこで止まる。
cdコマンドを順に実行したときの行き先と同じ考え方です(No.3はcd aのあとcd /bをして/b、No.4は/b/c) - resolveは絶対パスにならなければcwdを前に足す。 No.1・5・7・11・13・14がこれに当たります
- 空の結果は、joinでは
.、resolveではcwd。 引数なしのpath.resolve()はprocess.cwd()と同じ値でした - 末尾の
/はjoinでは残り、resolveでは取り除かれる。 No.10がこの違いです
No.2とNo.12のように、先頭の引数が絶対パスで、あとの引数が / で始まらない場合は、両方とも同じ結果になります。path.join(__dirname, 'data', 'a.txt') と path.resolve(__dirname, 'data', 'a.txt') が同じ値になるのはこのためです。
どちらを使うかの判断表
| 状況 | 向いているもの | 理由 |
|---|---|---|
| 自分のファイルの場所を基準に、決まった相対位置を指す | path.join(__dirname, ...) |
結果が引数だけで決まり、cwdに左右されない |
| コマンドの引数などで受け取ったパスを絶対パスにする | path.resolve(input) |
相対ならcwd基準、絶対ならそのまま、と利用者の感覚に合う |
| 基準フォルダと、絶対かもしれないパスを組み合わせる | path.resolve(base, input) |
絶対パスが来たらそちらを優先できる |
| 相対パスのまま部品をつなげたい(URLの一部、表示用など) | path.join(...) |
cwdが足されない |
| 設定ファイルに書かれた相対パスを、設定ファイルの場所を基準に解決する | path.resolve(path.dirname(configPath), value) |
相対・絶対のどちらが書かれても扱える |
「結果をcwdに左右されたくないときはjoinに絶対パスの基準を渡す、相対でも絶対でも受け取りたいときはresolve」と覚えると選びやすくなります。
WindowsとmacOS・Linuxでの結果の違い
同じ引数のOS別の結果
同じ14パターンを path.win32 でも実行しました。違いが出る主なものを並べます。
| 引数 | 関数 | macOS・Linux | Windows |
|---|---|---|---|
'a', 'b', 'c.txt' |
join | a/b/c.txt |
a\b\c.txt |
'a', 'b', 'c.txt' |
resolve | /home/taro/app/a/b/c.txt |
(cwd)\a\b\c.txt |
'/a', 'b' |
join | /a/b |
\a\b |
'a', '/b' |
resolve | /b |
\b(実機では現在のドライブが付く) |
'a', '../b' |
join | b |
b |
'a/b', '../../..', 'c' |
join | ../c |
..\c |
'a/', '/b/' |
join | a/b/ |
a\b\ |
'/a/b', '../c', './d.txt' |
join | /a/c/d.txt |
\a\c\d.txt |
'' |
join | . |
. |
Windows形式では、引数に / を書いても結果は \ にそろえられます。 逆にmacOS・Linux形式では \ は区切りではなく普通の文字として扱われます。
ドライブ文字を含むパス(Windows形式)
| 引数 | path.win32.join | path.win32.resolve |
|---|---|---|
'C:\\app', 'data', 'a.txt' |
C:\app\data\a.txt |
C:\app\data\a.txt |
'C:\\app', '\\data' |
C:\app\data |
C:\data |
'C:\\app', 'D:\\data' |
C:\app\D:\data |
D:\data |
'C:\\app', '..', 'x' |
C:\x |
C:\x |
'C:/app', 'sub/file.txt' |
C:\app\sub\file.txt |
C:\app\sub\file.txt |
'\\\\server\\share', 'dir', 'a.txt' |
\\server\share\dir\a.txt |
\\server\share\dir\a.txt |
ここでもjoinとresolveの性格の違いが出ます。別ドライブの絶対パスを渡すと、joinはそのままつなげて C:\app\D:\data という使えないパスになり、resolveは D:\data に切り替えます。 利用者が入力したパスを受け取る処理ではresolveが向いています。
OSによって変わる値の一覧
| 項目 | macOS・Linux | Windows |
|---|---|---|
path.sep |
/ |
\ |
path.delimiter(PATH環境変数の区切り) |
: |
; |
| 絶対パスの例 | /home/taro/app |
C:\Users\taro\app |
isAbsolute('C:\\a') |
false |
true |
isAbsolute('\\a') |
false |
true |
basename('C:\\app\\a.txt') |
C:\app\a.txt(全体が1つの名前) |
a.txt |
normalize('C:/app//src/../a.txt') |
C:/app/a.txt |
C:\app\a.txt |
relative('C:\\app\\src', 'C:\\app\\public')(win32) |
— | ..\public |
relative('C:\\app', 'D:\\data')(win32) |
— | D:\data(ドライブが違うと絶対パスが返る) |
parse('C:\\app\\src\\a.txt').root(win32) |
— | C:\ |
Windowsで作られたパス文字列をLinuxのサーバーで処理するような場面では、path.basename がパス全体を返します。相手のOSが決まっているときは、path.win32.basename(...) のようにOSを明示した入口を使うと、動かす場所に関係なく同じ結果になります。
OSの違いを吸収する書き方
| 書き方 | 結果 |
|---|---|
'data/' + name と文字列でつなぐ |
Windowsでも多くの場面で動くが、\ と / が混ざった表示になる |
path.join('data', name) |
動かしているOSの区切り文字でそろう |
p.split(path.sep) |
動かしているOSの区切りで分割できる |
p.split(path.win32.sep).join(path.posix.sep) |
\ を / に置き換える(URLや設定ファイル向け) |
process.env.PATH.split(path.delimiter) |
PATH環境変数をOSに合った区切りで分割できる |
入出力早見表:分解する・組み立てる・整える
ここからの結果は、すべてmacOS・Linux形式での実行結果です。
basename・dirname・extname
| 呼び出し | 結果 |
|---|---|
path.basename('/home/taro/app/src/report.final.tar.gz') |
report.final.tar.gz |
path.basename('/home/taro/app/src/report.final.tar.gz', '.gz') |
report.final.tar |
path.basename('/home/taro/app/') |
app(末尾の / は無視される) |
path.dirname('/home/taro/app/src/report.final.tar.gz') |
/home/taro/app/src |
path.dirname('/home/taro/app/') |
/home/taro |
path.dirname('file.txt') |
. |
path.extname('report.final.tar.gz') |
.gz(最後のドットから後ろだけ) |
path.extname('.bashrc') |
''(先頭ドットだけの名前は拡張子なし) |
path.extname('README') |
'' |
path.extname('a.') |
. |
.tar.gz のような二重の拡張子は、extnameでは .gz だけが返ります。 .tar.gz 全体を扱いたいときは、name.endsWith('.tar.gz') のように文字列として判定します。
parseとformat
path.parse はパスを5つの部品に分け、path.format はその逆を行います。
console.log(path.parse('/home/taro/app/src/report.final.tar.gz'));
{
root: '/',
dir: '/home/taro/app/src',
base: 'report.final.tar.gz',
ext: '.gz',
name: 'report.final.tar'
}
| 部品 | 上の例での値 | 意味 |
|---|---|---|
| root | / |
ルート(Windows形式では C:\ など) |
| dir | /home/taro/app/src |
フォルダ部分(rootを含む) |
| base | report.final.tar.gz |
ファイル名全体(name + ext) |
| name | report.final.tar |
拡張子を除いたファイル名 |
| ext | .gz |
拡張子(最後のドットから後ろ) |
「dir + 区切り文字 + base」で元のパスに戻り、baseは「name + ext」に分かれる、という2段の関係です。formatの例を並べます。
| 呼び出し | 結果 | 決まり |
|---|---|---|
path.parse('.bashrc') |
{ root: '', dir: '', base: '.bashrc', ext: '', name: '.bashrc' } |
先頭ドットの名前はnameに入る |
path.format({ dir: '/home/taro', base: 'a.txt' }) |
/home/taro/a.txt |
dir + 区切り + base |
path.format({ dir: '/x', name: 'a', ext: '.md' }) |
/x/a.md |
baseがなければname + ext |
path.format({ dir: '/x', name: 'a', ext: 'md' }) |
/x/a.md |
extにドットがなければ補われる |
path.format({ root: '/', base: 'a.txt', ext: '.md' }) |
/a.txt |
baseがあるとnameとextは使われない |
path.format({ root: '/r', dir: '/x', base: 'a.txt' }) |
/x/a.txt |
dirがあるとrootは使われない |
formatの優先順位は「dirがrootより優先」「baseがname + extより優先」の2つです。parseした結果の拡張子だけを変えたいときは、baseを渡さずにnameとextを渡します(次の「コピペ用の実例」を参照)。
relative・normalize・isAbsolute・sep
| 呼び出し | 結果 |
|---|---|
path.relative('/home/taro/app/src', '/home/taro/app/public/img') |
../public/img |
path.relative('/a/b', '/a/b/c/d') |
c/d |
path.relative('/a/b', '/a/b') |
''(同じ場所は空文字) |
path.normalize('/a//b/../c/./d/') |
/a/c/d/(末尾の / は残る) |
path.normalize('') |
. |
path.normalize('a/../..') |
.. |
path.isAbsolute('/a') |
true |
path.isAbsolute('./a') |
false |
path.sep |
/ |
path.delimiter |
: |
path.matchesGlob('/a/b.js', '/a/*.js') |
true |
path.win32.toNamespacedPath('C:\\app') |
\\?\C:\app |
path.matchesGlob は比較的新しい関数で、今回は20.20.2で関数として存在すること、22.22.2と24.21.0で上の結果になることを確認しました。18.20.8では typeof path.matchesGlob が undefined だったため、複数の版で動かすコードでは存在を確かめてから使います。
文字列以外を渡したとき
path.join('a', null);
TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received null
pathの関数は文字列だけを受け取ります。 環境変数や設定値が未設定で undefined のまま渡るとこのエラーになるので、渡す前に既定値を入れておくと安定します。
ESMでの__dirnameの置き換え方
CommonJSでは __dirname(そのファイルがあるフォルダ)と __filename(そのファイルのパス)が最初から使えます。ESM(.mjs、または "type": "module" の .js)にはこの2つがないため、次のどちらかで置き換えます。
方法1:import.meta.dirname(Node.js 20.11以降)
// esm.mjs
import path from 'node:path';
console.log('import.meta.dirname :', import.meta.dirname);
console.log('import.meta.filename :', import.meta.filename);
console.log(path.join(import.meta.dirname, 'data', 'a.txt'));
import.meta.dirname : /home/taro/app
import.meta.filename : /home/taro/app/esm.mjs
/home/taro/app/data/a.txt
公式ドキュメントでは、追加された版はv20.11.0 / v21.2.0、安定版になったのはv22.16.0 / v24.0.0と記載されています。file: のモジュールでだけ使える点も書かれています。
方法2:fileURLToPath(ESMが使える全版)
// esm.mjs
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
console.log('import.meta.url :', import.meta.url);
console.log('__filename :', __filename);
console.log('__dirname :', __dirname);
import.meta.url : file:///home/taro/app/esm.mjs
__filename : /home/taro/app/esm.mjs
__dirname : /home/taro/app
版ごとの結果と選び方
| 版 | import.meta.dirname |
fileURLToPath(import.meta.url) |
|---|---|---|
| 18.20.8 | undefined |
動く |
| 20.18.3 | /home/taro/app |
動く |
| 22.22.2 | /home/taro/app |
動く |
| 24.21.0 | /home/taro/app |
動く |
fileURLToPath の列は、18.20.8 / 20.18.3 / 20.20.2 / 22.11.0 / 22.22.2 / 24.21.0で同じ書き方が動くことを確認しています。
| 状況 | 向いている書き方 |
|---|---|
| Node.js 20.11以降だけで動かす | import.meta.dirname |
| 18系でも動かす、配布するライブラリ | fileURLToPath(import.meta.url) + path.dirname |
| CommonJS | __dirname |
URLのpathnameをそのまま使わない
new URL('./x', import.meta.url).pathname でもパスらしい文字列が取れますが、日本語や空白が入ると結果が変わります。
const url = new URL('./デー タ/a.txt', import.meta.url);
console.log('URL.pathname :', url.pathname);
console.log('fileURLToPath :', fileURLToPath(url));
URL.pathname : /home/taro/app/%E3%83%87%E3%83%BC%20%E3%82%BF/a.txt
fileURLToPath : /home/taro/app/デー タ/a.txt
pathnameはURLとしてエンコードされた文字列なので、ファイルのパスとして使うときは fileURLToPath を通します。 逆にパスからURLを作るときは pathToFileURL を使います。
import { pathToFileURL } from 'node:url';
console.log(pathToFileURL('/home/taro/app/a b.txt').href);
file:///home/taro/app/a%20b.txt
コピペ用の実例
拡張子を差し替える・ファイル名の末尾に文字を足す
const path = require('node:path');
function replaceExt(file, ext) {
const { dir, name } = path.parse(file);
return path.format({ dir, name, ext });
}
function addSuffix(file, suffix) {
const { dir, name, ext } = path.parse(file);
return path.format({ dir, name: name + suffix, ext });
}
console.log(replaceExt('/home/taro/app/docs/guide.md', '.html'));
console.log(addSuffix('/home/taro/app/img/photo.png', '@2x'));
/home/taro/app/docs/guide.html
/home/taro/app/img/photo@2x.png
parseの結果からbaseを外し、nameとextを渡すのがポイントです。baseを残したままだと、formatはbaseを優先して元のファイル名を返します。
基準フォルダの外を指していないか確かめる
利用者が入力したファイル名を基準フォルダの下で開くときは、組み立てたあとに「基準フォルダの内側か」を確かめます。
const path = require('node:path');
function resolveInside(baseDir, userPath) {
const target = path.resolve(baseDir, userPath);
const rel = path.relative(baseDir, target);
const inside = rel !== '' && !rel.startsWith('..') && !path.isAbsolute(rel);
return { target, rel, inside };
}
console.log(resolveInside('/home/taro/app/uploads', 'a/b.png'));
console.log(resolveInside('/home/taro/app/uploads', '../secret.txt'));
console.log(resolveInside('/home/taro/app/uploads', '/etc/hosts'));
{
target: '/home/taro/app/uploads/a/b.png',
rel: 'a/b.png',
inside: true
}
{
target: '/home/taro/app/secret.txt',
rel: '../secret.txt',
inside: false
}
{ target: '/etc/hosts', rel: '../../../../etc/hosts', inside: false }
resolveで絶対パスにしてから、relativeの結果が .. で始まらないことを確かめる流れです。joinだけでは .. を含む入力が基準フォルダの外へ出ることがあるため、入力を受け取る処理ではこの確認を入れておくと安心です。rel !== '' の条件は、基準フォルダそのものを指す入力(空文字や .)を対象外にするためのものです。フォルダ自体を許可したい処理では、この条件を外します。シンボリックリンクまで考える場合は、fs.realpath で実際のパスに直してから比べます(この部分は未実行)。
区切り文字を / にそろえる・PATHを分割する
const toPosix = (p) => p.split(path.win32.sep).join(path.posix.sep);
console.log(toPosix('src\\components\\Button.vue'));
console.log('/usr/local/bin:/usr/bin:/bin'.split(path.delimiter));
src/components/Button.vue
[ '/usr/local/bin', '/usr/bin', '/bin' ]
つまずきやすい箇所と直し方
| 起きること | 理由 | 直し方 |
|---|---|---|
path.resolve('data', '/a.txt') が /a.txt になる |
resolveは絶対パスが現れたら左側を捨てる | つなげたいだけなら path.join を使う |
| 実行する場所によって結果が変わる | 相対パスをresolveするとcwdが基準になる | __dirname / import.meta.dirname を基準にする |
__dirname is not defined in ES module scope |
ESMには __dirname がない |
import.meta.dirname、または fileURLToPath |
import.meta.dirname が undefined |
Node.jsが20.11より前 | path.dirname(fileURLToPath(import.meta.url)) |
extname('a.tar.gz') が .gz |
最後のドットから後ろだけを返す | endsWith('.tar.gz') で判定する |
format で拡張子が変わらない |
baseがnameとextより優先される | baseを渡さずnameとextを渡す |
| Linux上でWindowsのパスのbasenameが取れない | \ が区切りとして扱われない |
path.win32.basename を使う |
日本語を含むパスが %E3%83... になる |
URLのpathnameをそのまま使っている | fileURLToPath を通す |
The "path" argument must be of type string |
undefined や null を渡している |
渡す前に既定値を入れる |
書く前のチェックリスト
| 確認すること | 目安 |
|---|---|
パスを + で文字列連結していないか |
path.join に置き換える |
| 相対パスの基準は決まっているか | ファイルの場所なら __dirname / import.meta.dirname、利用者の入力ならcwd |
resolveに / で始まる引数を渡していないか |
渡すと左側が捨てられる |
ESMで __dirname を使っていないか |
import.meta.dirname(20.11以降)または fileURLToPath |
| 入力されたパスが基準フォルダの外へ出ないか | resolve + relativeで確かめる |
| 別のOSで作られたパスを処理していないか | path.win32 / path.posix を明示する |
| 二重の拡張子を扱っていないか | extnameは最後の1つだけを返す |
よくある質問
Q. path.joinとpath.resolveはどう使い分けますか?
A. joinは渡した部品をつなげて整えるだけで、cwdを使いません。resolveは右から順にたどって必ず絶対パスを返し、絶対パスにならないときはcwdを前に足します。ファイルの場所を基準に決まった位置を指すなら path.join(__dirname, ...)、利用者から受け取った相対・絶対どちらもありうるパスを扱うなら path.resolve(...) が向いています。
Q. ESMで__dirnameを使うにはどうすればよいですか?
A. Node.js 20.11以降なら import.meta.dirname がそのまま使えます。18系でも動かす場合は、fileURLToPath(import.meta.url) でファイルのパスを取り出し、path.dirname でフォルダ部分にします。今回の実行では、18.20.8で import.meta.dirname は undefined、20.18.3以降ではフォルダのパスが返りました。
Q. Windowsでも同じコードで動きますか?
A. path.join や path.resolve を使っていれば、区切り文字はOSに合わせて自動で切り替わります。違いが出るのは、パスを / で直接分割している箇所や、別のOSで作られたパス文字列を処理する箇所です。前者は path.sep、後者は path.win32 / path.posix を使うとそろえられます。この記事のWindows形式の結果は path.win32 をLinux上で動かしたもので、実機での実行は未実行です。
Q. path.parseとpath.formatはどんなときに使いますか? A. ファイル名の一部だけを変えたいときに便利です。parseでroot・dir・base・name・extに分け、変えたい部品を差し替えてformatで組み立て直します。拡張子を変えるときは、baseを渡さずnameとextを渡すのがポイントです。
まとめ
- joinは「つなげて整える」、resolveは「右からたどって必ず絶対パスを返す」
- resolveは途中に絶対パスがあると左側を捨てる(
resolve('a', '/b')は/b)。joinは部品としてつなげる(a/b) - cwdに左右されたくないときは
path.join(__dirname, ...)、ESMではimport.meta.dirname(20.11以降) - 18系でも動かすESMは
path.dirname(fileURLToPath(import.meta.url)) - extnameは最後のドットから後ろだけ、formatは「dirがrootより優先」「baseがname + extより優先」
- Windows形式では区切りが
\にそろい、別ドライブの絶対パスはresolveが切り替える - 入力されたパスはresolve + relativeで基準フォルダの内側か確かめる
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Node.js pathモジュールの使い方|joinとresolveの違い早見表」
株式会社RJCでは、Node.jsのパス操作の考え方を仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。