How do you get a list of the names of all files present in a directory in Node.js?

后端 未结 25 1165
天涯浪人
天涯浪人 2020-11-22 07:47

I\'m trying to get a list of the names of all the files present in a directory using Node.js. I want output that is an array of filenames. How can I do this?

相关标签:
25条回答
  • 2020-11-22 08:11

    This is a TypeScript, optionally recursive, optionally error logging and asynchronous solution. You can specify a regular expression for the file names you want to find.

    I used fs-extra, because its an easy super set improvement on fs.

    import * as FsExtra from 'fs-extra'
    
    /**
     * Finds files in the folder that match filePattern, optionally passing back errors .
     * If folderDepth isn't specified, only the first level is searched. Otherwise anything up
     * to Infinity is supported.
     *
     * @static
     * @param {string} folder The folder to start in.
     * @param {string} [filePattern='.*'] A regular expression of the files you want to find.
     * @param {(Error[] | undefined)} [errors=undefined]
     * @param {number} [folderDepth=0]
     * @returns {Promise<string[]>}
     * @memberof FileHelper
     */
    public static async findFiles(
        folder: string,
        filePattern: string = '.*',
        errors: Error[] | undefined = undefined,
        folderDepth: number = 0
    ): Promise<string[]> {
        const results: string[] = []
    
        // Get all files from the folder
        let items = await FsExtra.readdir(folder).catch(error => {
            if (errors) {
                errors.push(error) // Save errors if we wish (e.g. folder perms issues)
            }
    
            return results
        })
    
        // Go through to the required depth and no further
        folderDepth = folderDepth - 1
    
        // Loop through the results, possibly recurse
        for (const item of items) {
            try {
                const fullPath = Path.join(folder, item)
    
                if (
                    FsExtra.statSync(fullPath).isDirectory() &&
                    folderDepth > -1)
                ) {
                    // Its a folder, recursively get the child folders' files
                    results.push(
                        ...(await FileHelper.findFiles(fullPath, filePattern, errors, folderDepth))
                    )
                } else {
                    // Filter by the file name pattern, if there is one
                    if (filePattern === '.*' || item.search(new RegExp(filePattern, 'i')) > -1) {
                        results.push(fullPath)
                    }
                }
            } catch (error) {
                if (errors) {
                    errors.push(error) // Save errors if we wish
                }
            }
        }
    
        return results
    }
    
    0 讨论(0)
  • 2020-11-22 08:12

    Using Promises with ES7

    Asynchronous use with mz/fs

    The mz module provides promisified versions of the core node library. Using them is simple. First install the library...

    npm install mz
    

    Then...

    const fs = require('mz/fs');
    fs.readdir('./myDir').then(listing => console.log(listing))
      .catch(err => console.error(err));
    

    Alternatively you can write them in asynchronous functions in ES7:

    async function myReaddir () {
      try {
        const file = await fs.readdir('./myDir/');
      }
      catch (err) { console.error( err ) }
    };
    

    Update for recursive listing

    Some of the users have specified a desire to see a recursive listing (though not in the question)... Use fs-promise. It's a thin wrapper around mz.

    npm install fs-promise;
    

    then...

    const fs = require('fs-promise');
    fs.walk('./myDir').then(
        listing => listing.forEach(file => console.log(file.path))
    ).catch(err => console.error(err));
    
    0 讨论(0)
  • 2020-11-22 08:12

    Here's an asynchronous recursive version.

        function ( path, callback){
         // the callback gets ( err, files) where files is an array of file names
         if( typeof callback !== 'function' ) return
         var
          result = []
          , files = [ path.replace( /\/\s*$/, '' ) ]
         function traverseFiles (){
          if( files.length ) {
           var name = files.shift()
           fs.stat(name, function( err, stats){
            if( err ){
             if( err.errno == 34 ) traverseFiles()
        // in case there's broken symbolic links or a bad path
        // skip file instead of sending error
             else callback(err)
            }
            else if ( stats.isDirectory() ) fs.readdir( name, function( err, files2 ){
             if( err ) callback(err)
             else {
              files = files2
               .map( function( file ){ return name + '/' + file } )
               .concat( files )
              traverseFiles()
             }
            })
            else{
             result.push(name)
             traverseFiles()
            }
           })
          }
          else callback( null, result )
         }
         traverseFiles()
        }
    
    0 讨论(0)
  • 2020-11-22 08:16

    As of Node v10.10.0, it is possible to use the new withFileTypes option for fs.readdir and fs.readdirSync in combination with the dirent.isDirectory() function to filter for filenames in a directory. That looks like this:

    fs.readdirSync('./dirpath', {withFileTypes: true})
    .filter(item => !item.isDirectory())
    .map(item => item.name)
    

    The returned array is in the form:

    ['file1.txt', 'file2.txt', 'file3.txt']
    

    Docs for the fs.Dirent class

    0 讨论(0)
  • 2020-11-22 08:16

    Took the general approach of @Hunan-Rostomyan, made it a litle more concise and added excludeDirs argument. It'd be trivial to extend with includeDirs, just follow same pattern:

    import * as fs from 'fs';
    import * as path from 'path';
    
    function fileList(dir, excludeDirs?) {
        return fs.readdirSync(dir).reduce(function (list, file) {
            const name = path.join(dir, file);
            if (fs.statSync(name).isDirectory()) {
                if (excludeDirs && excludeDirs.length) {
                    excludeDirs = excludeDirs.map(d => path.normalize(d));
                    const idx = name.indexOf(path.sep);
                    const directory = name.slice(0, idx === -1 ? name.length : idx);
                    if (excludeDirs.indexOf(directory) !== -1)
                        return list;
                }
                return list.concat(fileList(name, excludeDirs));
            }
            return list.concat([name]);
        }, []);
    }
    

    Example usage:

    console.log(fileList('.', ['node_modules', 'typings', 'bower_components']));
    
    0 讨论(0)
  • 2020-11-22 08:17

    I made a node module to automate this task: mddir

    Usage

    node mddir "../relative/path/"

    To install: npm install mddir -g

    To generate markdown for current directory: mddir

    To generate for any absolute path: mddir /absolute/path

    To generate for a relative path: mddir ~/Documents/whatever.

    The md file gets generated in your working directory.

    Currently ignores node_modules, and .git folders.

    Troubleshooting

    If you receive the error 'node\r: No such file or directory', the issue is that your operating system uses different line endings and mddir can't parse them without you explicitly setting the line ending style to Unix. This usually affects Windows, but also some versions of Linux. Setting line endings to Unix style has to be performed within the mddir npm global bin folder.

    Line endings fix

    Get npm bin folder path with:

    npm config get prefix

    Cd into that folder

    brew install dos2unix

    dos2unix lib/node_modules/mddir/src/mddir.js

    This converts line endings to Unix instead of Dos

    Then run as normal with: node mddir "../relative/path/".

    Example generated markdown file structure 'directoryList.md'

        |-- .bowerrc
        |-- .jshintrc
        |-- .jshintrc2
        |-- Gruntfile.js
        |-- README.md
        |-- bower.json
        |-- karma.conf.js
        |-- package.json
        |-- app
            |-- app.js
            |-- db.js
            |-- directoryList.md
            |-- index.html
            |-- mddir.js
            |-- routing.js
            |-- server.js
            |-- _api
                |-- api.groups.js
                |-- api.posts.js
                |-- api.users.js
                |-- api.widgets.js
            |-- _components
                |-- directives
                    |-- directives.module.js
                    |-- vendor
                        |-- directive.draganddrop.js
                |-- helpers
                    |-- helpers.module.js
                    |-- proprietary
                        |-- factory.actionDispatcher.js
                |-- services
                    |-- services.cardTemplates.js
                    |-- services.cards.js
                    |-- services.groups.js
                    |-- services.posts.js
                    |-- services.users.js
                    |-- services.widgets.js
            |-- _mocks
                |-- mocks.groups.js
                |-- mocks.posts.js
                |-- mocks.users.js
                |-- mocks.widgets.js
    
    0 讨论(0)
提交回复
热议问题