Arman
Arman

Reputation: 2925

fs.readFileSync is not file relative? Node.js

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?

Upvotes: 215

Views: 134646

Answers (4)

Shiva127
Shiva127

Reputation: 2623

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'))

Upvotes: 2

Renatex
Renatex

Reputation: 1054

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

Upvotes: 5

Stephen Jenkins
Stephen Jenkins

Reputation: 1836

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'));

Upvotes: 21

cartant
cartant

Reputation: 58400

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"));

Upvotes: 338

Related Questions