0

I want to be able to find target.json by passing a path to startingPoint.txt to a function in Node JS, given the following folder structure:

- root
 - sub1
  - sub2
    startingPoint.txt
 target.json

I've found a node package for it called find-up, but this is the kind of thing that probably takes no more than 6 lines of code.


export function findUp(start: Path, target: string): Path | undefined {
  // this code here
}

const pathToTarget = findUp("root/sub1/sub2/startingPoint.txt", "target.json"/);
console.log(pathToTarget); // "root/target.json"

2 Answers 2

1

Old question I know, but I've just had to implement something similar and spent ages trying to find a good solution.

So, for future explorers, heres my solution using path and fs modules.

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

function findInPathAncestry(path, target) {

    let current_directory_path = PATH.normalize(path).split(PATH.sep);
    let result = false;

    while(current_directory_path.length && !result) {

        let current_path = current_directory_path.join(PATH.sep)+PATH.sep+target;

        if(FS.existsSync(current_path)) {

             result = current_path;
        }

        current_directory_path.pop();
    }

    return result;
}

usage example:

// example file structure:
// C:\
// | - path\
// | --- to\
// | ----- start\
// | ------- at\
// | ----- findme.txt


let start_location = "C:\path\to\start\at";
let target_file    = "findme.txt";

console.log(findInPathAncestry(start_location, target_file));

// expected output:
// C:\path\to\findme.txt
// or false if file doesn't exist in path

the use of PATH.normalize and PATH.sep allows this to work in windows and unix environments

https://nodejs.org/api/path.html#path_path_sep

Sign up to request clarification or add additional context in comments.

Comments

0

Here's what I have for now:

import { join, dirname } from 'path';
import { existsSync } from 'fs';

export let MAX_BACK_STEPS = 50;

export function findUp(start: string, target: string, boundary?: {
  path: string,
  inclusive: boolean,
}): string | null {
  let currentDir = dirname(start);
  let lastTry = false;
  let backSteps = 0;
  while (backSteps++) {
    if (backSteps >= MAX_BACK_STEPS) {
      console.error("Too many back steps");
      return null;
    }

    if (boundary && boundary.path.includes(currentDir)) {
      if (boundary.inclusive && lastTry === false) {
        lastTry = true;
      } else {
        return null;
      }
    }

    const targetTestPath = join(currentDir, target);
    if (existsSync(targetTestPath)) {
      return targetTestPath;
    }

    currentDir = join(currentDir, "../");
  }
}

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.