Trevor Burnham
Trevor Burnham

Reputation: 77416

How do I find out whether a file is within a directory with Node.js?

Given two absolute or relative paths, A and B, I want to find out whether B is "inside of" the directory A—not just in the directory itself, but potentially in a subdirectory. I'd like to do this without a potentially huge number of fs.readdir calls.

For instance, if A is / and B is /foo/bar/baz, it should be pretty obvious that B is within A; the recursive readdir approach would be extremely inefficient.

One obvious idea is to convert both paths to absolute form, then check if the string form of B's absolute path starts with the string form of A's. However, there are two problems:

  1. How do you convert the relative paths to absolute paths?
  2. What about symbolic links and such?

I'll accept answers that make calls to Linux utilities (other than rm -rf... which technically could be used to solve the problem) or third-party Node libraries.

Upvotes: 8

Views: 6051

Answers (2)

mak
mak

Reputation: 13405

var fs = require('fs');

var a = fs.realpathSync('/home/mak/www'); // /var/www
var b = fs.realpathSync('/var/www/test/index.html');

var b_in_a = b.indexOf(a) == 0;

var a_is_dir = fs.statSync(a).isDirectory();

fs.*Sync also have asynchronous versions, see fs module.

fs.realpathSync and fs.statSyncwill throw if the path does not exist.

Upvotes: 10

DS.
DS.

Reputation: 24110

I suggest this:

const path = require('path')

function isWithin(outer, inner) {
    const rel = path.relative(outer, inner);
    return !rel.startsWith('../') && rel !== '..';
}

It uses path.relative to compute the path of inner relative to outer. If it's not contained, the first component of the resulting path will be .., so that's what we check for.

Upvotes: 4

Related Questions