217

Suppose I have a file at the root of my project called file.xml.

Suppose I have a test file in tests/ called "test.js" and it has

const file = fs.readFileSync("../file.xml");

If I now run node ./tests/test.js from the root of my project it says ../file.xml does not exist. If I run the same command from within the tests directory, then it works.

It seems fs.readFileSync is relative to the directory where the script is invoked from, instead of where the script actually is. If I wrote fs.readFileSync("./file.xml") in test.js it would look more confusing and is not consistent with relative paths in a require statement which are file relative.

Why is this? How can I avoid having to rewrite the paths in my fs.readFileSync?

1
  • 6
    __dirname is not necessarily the same as the current working directory, but fs.readFileSync() uses the current working directory. The current working directory is likely set to whatever it was when you launched node. Commented Jun 17, 2017 at 6:11

4 Answers 4

342

You can resolve the path relative the location of the source file - rather than the current directory - using path.resolve:

const path = require("path");
const file = fs.readFileSync(path.resolve(__dirname, "../file.xml"));
Sign up to request clarification or add additional context in comments.

4 Comments

Because relative paths are resolved using the current directory. And you want to resolve using a different directory. From the docs: "The relative path to a filename can be used. Remember, however, that this path will be relative to process.cwd()."
for some reason I got it into my head that because local file wasn't working on my remote environment that i . would need to get the file by a full url. However, of course I didn't and I was able to use this method to resolve the absolute path on my remote server..
Note - path is a node module that provides utilities for working with file and directory paths. __dirname is a node.js environment variable that point to the parent directory of the current file.
I will just add to take a look at the cosole... maybe some "../" is missing. It works like a charm!
21

Just to expand on the above, if you are using fs.readFileSync with TypeScript (and of course CommonJS) here's the syntax:

import fs from 'fs';
import path from 'path';

const logo = fs.readFileSync(path.resolve(__dirname, './assets/img/logo.svg'));

This is because fs.readFileSync() is resolved relative to the current working directory, see the Node.js File System docs for more info.

Source: Relative fs.readFileSync paths with Node.js

And of course, the CommonJS format:

const fs = require('fs');
const path = require('path');

const logo = fs.readFileSync(path.resolve(__dirname, './assets/img/logo.svg'));

3 Comments

Not sure I see how this expands the accepted answer, it seems exactly the same to me - path.resolve with __dirname and a relative path.
@404 Yes I was including for TypeScript folks :) the code is the same but using import statements.
__dirname does not work in ESM, so the first example will not compile.
5

Another alternative if you are using type module is to use process.cwd()

package.json

{
    "type": "module",
}

console.log(process.cwd() + relative_path) // /User/your_user/path_to_folder

Comments

3

If you are using ES modules ("type": "module"), you can get the module path from import.meta.url:

import { fileURLToPath } from 'url'
import { dirname, resolve } from 'path'
import { readFileSync } from 'fs'

const modulePath = dirname(fileURLToPath(import.meta.url))

const file = readFileSync(resolve(modulePath, '../file.xml'))

or

import { readFileSync } from 'fs';

const file = readFileSync(new URL('../file.xml', import.meta.url));

Since Node.js version 20.11.0 you can call import.meta.dirname and import.meta.filename.

import { resolve } from 'path'
import { readFileSync } from 'fs'

const file = readFileSync(resolve(import.meta.dirname, '../file.xml'))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.