2

Is there a way to check whether a file exists in NodeJS, with case-sensitivity, even when the underlying file system isn't case sensitive?

fs.exists() may or may not be case sensitive depending on the underlying file system.

 fs = require('fs');
 fs.existsSync('readme.txt') // true
 fs.existsSync('README.TXT') // false (or true, depending on the file system)

This causes problems when developing an app on a case-insensitive development environment that will be deployed on a case-sensitive server. I recently had an issue where the build was broken by a typo. It worked locally.

If I can get Node to tell me, "yes, README.TXT exists, and it's stored as readme.txt" that will be enough to solve the problem.

admdrew
  • 3,790
  • 4
  • 27
  • 39
Patrick McElhaney
  • 57,901
  • 40
  • 134
  • 167

4 Answers4

6

Following Andrey's suggestion I implemented a function that uses readdir.

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

function fileExistsWithCaseSync(filepath) {
    var dir = path.dirname(filepath);
    if (dir === '/' || dir === '.') return true;
    var filenames = fs.readdirSync(dir);
    if (filenames.indexOf(path.basename(filepath)) === -1) {
        return false;
    }
    return fileExistsWithCaseSync(dir);
}

console.log(fileExistsWithCaseSync(__dirname + '/README.txt')) // false
console.log(fileExistsWithCaseSync(__dirname + '/readme.txt')) // true

I wouldn't use this function in production because each call makes several synchronous trips to the filesystem. But it's good enough for my needs: preventing my local development server from serving Foo.js when the file is actually called foo.js (which won't work in production).

Community
  • 1
  • 1
Patrick McElhaney
  • 57,901
  • 40
  • 134
  • 167
2

Just to help someone who having this path problem.

The Patric's function pretty works for this case, but not solve the path issue. I found the true path module that actually solved my problem with case-sensitive paths on linux (ubuntu).

See more info here.

2

Since I can't comment < 50 rep I'll make a new post.

@patrik's solution was working nice except on windows because of the root check

I changed it to look like following:

function fileExistsWithCaseSync (filepath) {
  var dir = path.dirname(filepath)
  if (dir === path.dirname(dir)) {
    return true
  }
  var filenames = fs.readdirSync(dir)
  if (filenames.indexOf(path.basename(filepath)) === -1) {
    return false
  }
  return fileExistsWithCaseSync(dir)
}
Puck
  • 2,080
  • 4
  • 19
  • 30
0
var fs = require('fs');
var path = require('path');

function fileExistsWithCaseSync(filepath) {
    var dir = path.dirname(filepath);
    if (filepath=== '/' || filepath=== '.') return true;
    var filenames = fs.readdirSync(dir);
    if (filenames.indexOf(path.basename(filepath)) === -1) {
        return false;
    }
    return fileExistsWithCaseSync(dir);
}

console.log(fileExistsWithCaseSync('./README.txt')) // false
console.log(fileExistsWithCaseSync('./readme.txt')) // true

check filepath use fileExistsWithCaseSync no __dirname

W.Andy
  • 1