2

Reading directories recursivly is not the problem. There are many good libraries for it, for instance recursive-readdir.

I am searching for a solution to extract only the folder structure without any files etc.

Example folder structure:

src/app/_content
├── contact.md
├── disclaimer.md
├── imprint.md
├── index.md
├── news.md
├── vita.md
└── work
    ├── drawing
    │   └── Z-WV-2018-001
    │       ├── index.md
    │       └── Z-WV-2018-001-0.jpeg
    └── sculpture
        └── EMPTY DIRECTORY

The wished output is an array like that:

const dirs = [
  'work',
  'work/drawing',
  'work/sculpture'
]

Further Information: The following part is not explicitly part of that question. This will be an additional part for a better understand of the problem deep in the back of my brain.

This should not be that hard, but in addition I will need to extract in the second step an object like this:

const files = [
  'content.md',
  'disclaimer.md',
  'imprint.md',
  'index.md',
  'news.md',
  'vita.md',
  {
    'work': [
      {
        'drawing': [
          {
            'Z-WV-2018-001': [
              'index.md',
              'Z-WV-2018-001-0.jpeg'
            ],
          },
          {
            'sculpture': []
          }
        ]
      }
    ]
  }
]

dirs will be needed for a browser application to know the pathes to the files. files will be neded to get the corresponding files out of the directories.

For clarification, I am building a static page generator with Angular 6 and it is not possible to read client-sidely the folder structure. Therefore it is necessary to compile that structure and put it with an nodejs script into the published folder. So Angular will know where to look for that files.

Please write a comment, if you need more clarification. I just wanted to be exact as possible.

Michael W. Czechowski
  • 3,366
  • 2
  • 23
  • 50

3 Answers3

1

You can use fs.stat method or it's synchronous version: fs.statSync. The method returns a fs.Stats instance. fs.Stats instances have .isDirectory method which returns true when a path is a directory.

const fs = require('fs');
fs.stat('/pathname', (err, stats) => {
    if (err) throw err;
    const isDir = stats.isDirectory();
    // ...
});

You need to call the fs.stat function for each pathname.

If using a library is an option, you can also use the draxt package:

const $ = require('draxt');
(async() {
   const $app = await $('src/app/_content/**');
   const $dirs = $app.directories();
   // dirs is a draxt collection of directories
   const dirPaths = $dirs.map(el => el.pathName);
   // dirPaths is an array of directories' absolute pathNames
}());
Ram
  • 143,282
  • 16
  • 168
  • 197
1

The library you provided gives you the ability to customize what it ignores during its search. You should be able to do something like this (disclaimer: haven't tested this):

const recursive = require("recursive-readdir");

function ignoreFiles(file, stats) {
  return !stats.isDirectory();
}

recursive("some/path", [ignoreFiles], function (err, dirs) {
  console.log(dirs);
});
Tyler Zeller
  • 254
  • 2
  • 8
  • So clever. I did not realize to use a method instead of an array. – Michael W. Czechowski Oct 20 '18 at 17:46
  • Could you explain the syntax, please? I anticipate you've looked into the type defenitions of that library, found the `IgnoreFunction` and so on. But why you have not to provide any arguments inside `recursive` for the `ignoreFIles` method? – Michael W. Czechowski Oct 20 '18 at 17:53
  • 1
    The `recursive` function takes in an array of 'ignore' variables (in my example this is `[ignoreFiles]`). You can pass in strings or functions to this ignore array. If you pass in a string, it will ignore all files that match that string pattern. If you pass in a function, then that function will be called with the file object as the argument (and some more information in `stats`). If the function returns `true` then the file will be ignored by the search, otherwise it will be included. – Tyler Zeller Oct 20 '18 at 19:39
  • Nevertheless this is not the solution for that problem. Although `ignoreFiles()` could filter the directories, the module `recursive-readdir` will not be able to give the wanted output. It focuses natively on the files and not on the folders. Did you tried to test your code? – Michael W. Czechowski Oct 22 '18 at 16:11
0
const klawSync = require('klaw-sync')
const dir = 'src/app/_content'
const files = klawSync(dir, {
  nofile: true
})

console.log(files.map(item => {
  return item.path.slice(item.path.indexOf(dir) + dir.length + 1)
}))

There will be a native solution for that problem for sure, but I decided to solve it with the help of an external module klaw-sync.

Michael W. Czechowski
  • 3,366
  • 2
  • 23
  • 50