Menu

Módulo path do Node.js: path.join vs path.resolve

O módulo path monta e desmonta caminhos de arquivo do jeito certo para o sistema operacional. path.join junta segmentos; path.resolve transforma esses segmentos em um caminho absoluto, a partir da pasta atual.

Esta página tem editores executáveis. Edite, execute e veja a saída na hora.

path.join() junta segmentos de caminho com o separador certo e limpa .. e barras duplicadas, mas mantém o resultado relativo se você começou com um segmento relativo. path.resolve() faz o mesmo trabalho da direita para a esquerda e sempre retorna um caminho absoluto: ele parte do diretório de trabalho atual, e qualquer segmento absoluto no meio do caminho recomeça o caminho. Use join para montar um caminho, e resolve quando precisar de um absoluto.

Ele imprimiu users/ada/notes.txt, depois users/grace/todo.txt (o .. removeu ada), depois /srv/app/public/index.html e src/lib/utils.js: barras extras e segmentos vazios sumiram. O join nunca trata /public/ como um novo começo; é só o próximo segmento.

path.join vs path.resolve

A diferença aparece quando um segmento começa com / ou quando o primeiro segmento é relativo:

Com /public no meio, o join produziu /srv/app/public/img, enquanto o resolve descartou tudo antes dele e produziu /public/img; os dois trataram .. do mesmo jeito. As duas últimas linhas mostram que o join manteve public/index.html relativo, enquanto o resolve o tornou absoluto colocando a pasta atual na frente.

path.joinpath.resolve
ResultadoRelativo ou absoluto, como a entradaSempre absoluto
Um segmento que começa com /Só mais um segmentoRecomeça o caminho ali
Ponto de partidaNenhumO diretório de trabalho atual
Sem argumentos'.'O diretório de trabalho atual
Uso típicoMontar um caminho a partir de partesTransformar entrada do usuário ou config em caminho absoluto

basename, dirname, extname e parse

Estas funções desmontam um caminho. Elas só olham a string: o arquivo não precisa existir.

Ele imprimiu cat.final.jpg, cat.final, /home/ada/photos e .jpg: extname pega só a parte depois do último ponto. path.parse retorna tudo de uma vez (root, dir, base, ext, name), e path.format transforma um objeto desses de volta em string.

__dirname e __filename

Em um arquivo CommonJS, __dirname é o caminho absoluto da pasta que contém o arquivo, e __filename é o próprio arquivo. Um caminho relativo como 'data.json' é relativo ao lugar de onde o usuário rodou node, o que quebra assim que alguém inicia seu script de outra pasta. Monte os caminhos a partir de __dirname:

Ele imprimiu config.json dark e index.js. Os caminhos completos mudam em cada máquina, e é exatamente por isso que você os monta com path.join(__dirname, ...) em vez de digitá-los.

__dirname em ES modules: import.meta.dirname

ES modules não têm __dirname; usar lança ReferenceError: __dirname is not defined in ES module scope. Desde o Node.js 20.11, import.meta.dirname e import.meta.filename substituem os dois:

Ele imprimiu index.js e data/users.json. Em versões do Node.js anteriores à 20.11, obtenha a pasta a partir da URL do módulo: path.dirname(fileURLToPath(import.meta.url)), com fileURLToPath vindo de node:url.

Por que não juntar caminhos com strings

'data' + '/' + file funciona no macOS e no Linux e depois falha no Windows, onde o separador é \, e não resolve nada sobre .., barras duplicadas ou uma barra faltando. O path usa as regras do sistema em que está rodando. Você pode ver o resultado do Windows em qualquer máquina com 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

Passe o resultado de path.join para o fs.readFile e o mesmo código lê o arquivo em qualquer sistema.

Erros comuns

Esperar que extname entenda extensões duplas. path.extname('archive.tar.gz') é '.gz', e um dotfile como .env não tem extensão nenhuma: path.extname('.env') é ''. Verifique o fim do nome por conta própria quando o sufixo completo importar.

Confiar no join para manter o usuário dentro de uma pasta. path.join('/srv/app', '../../etc/passwd') é '/etc/passwd'. Antes de ler um arquivo cujo nome veio de uma requisição, resolva o caminho e confira se ele ainda começa com a sua pasta.

Perguntas frequentes

Qual a diferença entre __dirname e process.cwd()?

__dirname é a pasta do arquivo de código atual e nunca muda. process.cwd() é a pasta de onde o usuário rodou node. Os dois só são iguais quando o programa é iniciado da própria pasta.

Devo usar path.join ou path.resolve com __dirname?

Os dois funcionam para path.join(__dirname, 'data.json'), já que __dirname já é absoluto. Use resolve quando um segmento puder ser absoluto por conta própria, como um caminho digitado pelo usuário, e você quiser que esse caminho prevaleça.

Como uso o módulo path com URLs?

Não use: URLs sempre usam / e têm suas próprias regras para .. e query strings. Use a classe URL, como em new URL('../img/logo.png', 'https://example.com/docs/page').

Ilustração das linguagens de programação do Coddy

Aprenda a programar com o Coddy

Começar