Menu

Il modulo path di Node.js: path.join e path.resolve

Il modulo path costruisce e scompone i percorsi dei file nel modo giusto per il sistema operativo. path.join unisce i segmenti; path.resolve li trasforma in un percorso assoluto, partendo dalla cartella corrente.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

path.join() unisce i segmenti di un percorso con il separatore giusto e sistema i .. e le barre doppie, ma lascia il risultato relativo se sei partito da un segmento relativo. path.resolve() fa lo stesso lavoro da destra a sinistra e restituisce sempre un percorso assoluto: parte dalla directory di lavoro corrente, e ogni segmento assoluto che incontra fa ripartire il percorso. Usa join per costruire un percorso e resolve quando te ne serve uno assoluto.

Ha stampato users/ada/notes.txt, poi users/grace/todo.txt (il .. ha tolto ada), poi /srv/app/public/index.html e src/lib/utils.js: le barre in più e i segmenti vuoti sono spariti. join non tratta mai /public/ come un nuovo inizio; è solo il segmento successivo.

path.join e path.resolve a confronto

La differenza si vede quando un segmento inizia con / o quando il primo segmento è relativo:

Con /public nel mezzo, join ha prodotto /srv/app/public/img mentre resolve ha buttato via tutto quello che c'era prima e ha prodotto /public/img; entrambi hanno gestito .. allo stesso modo. Le ultime due righe mostrano che join ha lasciato relativo public/index.html, mentre resolve l'ha reso assoluto mettendo davanti la cartella corrente.

path.joinpath.resolve
RisultatoRelativo o assoluto, come l'inputSempre assoluto
Un segmento che inizia con /Un segmento come gli altriFa ripartire il percorso da lì
Punto di partenzaNessunoLa directory di lavoro corrente
Senza argomenti'.'La directory di lavoro corrente
Uso tipicoCostruire un percorso a partire dalle partiTrasformare un input dell'utente o una config in un percorso assoluto

basename, dirname, extname e parse

Queste funzioni scompongono un percorso. Guardano solo la stringa: il file non deve per forza esistere.

Ha stampato cat.final.jpg, cat.final, /home/ada/photos e .jpg: extname prende solo la parte dopo l'ultimo punto. path.parse restituisce tutto in una volta (root, dir, base, ext, name), e path.format ritrasforma un oggetto del genere in una stringa.

__dirname e __filename

In un file CommonJS, __dirname è il percorso assoluto della cartella che contiene il file, e __filename quello del file stesso. Un percorso relativo come 'data.json' è relativo al punto da cui l'utente ha eseguito node, e si rompe appena qualcuno avvia lo script da un'altra cartella. Costruisci invece i percorsi a partire da __dirname:

Ha stampato config.json dark e index.js. I percorsi completi cambiano su ogni macchina, ed è proprio per questo che li costruisci con path.join(__dirname, ...) invece di scriverli a mano.

__dirname nei moduli ES: import.meta.dirname

I moduli ES non hanno __dirname; usarlo lancia ReferenceError: __dirname is not defined in ES module scope. Da Node.js 20.11 li sostituiscono import.meta.dirname e import.meta.filename:

Ha stampato index.js e data/users.json. Nelle versioni di Node.js precedenti alla 20.11, ricava la cartella dall'URL del modulo: path.dirname(fileURLToPath(import.meta.url)), con fileURLToPath da node:url.

Perché non unire i percorsi con le stringhe

'data' + '/' + file funziona su macOS e Linux, poi fallisce su Windows, dove il separatore è \, e non fa niente per .., barre doppie o una barra mancante. path usa le regole del sistema su cui gira. Puoi vedere il risultato di Windows da qualsiasi macchina con path.win32:

const path = require('path');

path.posix.join('users', 'ada', 'notes.txt'); // 'users/ada/notes.txt'
path.win32.join('users', 'ada', 'notes.txt'); // 'users\\ada\\notes.txt'
path.sep;                                     // '/' on macOS and Linux, '\\' on Windows

Passa il risultato di path.join a fs.readFile e lo stesso codice legge il file su ogni sistema.

Errori comuni

Aspettarsi che extname conosca le doppie estensioni. path.extname('archive.tar.gz') è '.gz', e un file nascosto come .env non ha proprio estensione: path.extname('.env') è ''. Controlla tu la fine del nome quando ti serve il suffisso completo.

Contare su join per tenere un utente dentro una cartella. path.join('/srv/app', '../../etc/passwd') è '/etc/passwd'. Prima di leggere un file indicato da una richiesta, risolvi il percorso e controlla che inizi ancora con la tua cartella.

Domande frequenti

Che differenza c'è tra __dirname e process.cwd()?

__dirname è la cartella del file sorgente corrente e non cambia mai. process.cwd() è la cartella da cui l'utente ha eseguito node. Coincidono solo quando il programma viene avviato dalla sua cartella.

Con __dirname conviene path.join o path.resolve?

Per path.join(__dirname, 'data.json') vanno bene entrambi, perché __dirname è già assoluto. Usa resolve quando un segmento potrebbe essere a sua volta assoluto, come un percorso scritto dall'utente, e vuoi che sia quel percorso a vincere.

Come uso il modulo path con gli URL?

Non farlo: gli URL usano sempre / e hanno regole proprie per .. e le query string. Usa la classe URL, come in new URL('../img/logo.png', 'https://example.com/docs/page').

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

Inizia