Created
February 1, 2022 21:21
-
-
Save souporserious/bb17018b988dbd7ea39d8e54e868995f to your computer and use it in GitHub Desktop.
Recursively get files and meta information from a directory of files.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { promises as fs } from 'fs'; | |
import { basename, extname } from 'path'; | |
type Dirent = { | |
isFile(): boolean; | |
isDirectory(): boolean; | |
isBlockDevice(): boolean; | |
isCharacterDevice(): boolean; | |
isSymbolicLink(): boolean; | |
isFIFO(): boolean; | |
isSocket(): boolean; | |
name: string; | |
}; | |
export type FileFormat = { | |
/** Whether this is a file or directory type. */ | |
type: 'directory' | 'file'; | |
/** The file extension if it exists. */ | |
extension: string | null; | |
/** Any associated files in a directory type. */ | |
children: any[]; | |
/** Name of the file. */ | |
name: string; | |
/** Absolute path to the file. */ | |
path: string; | |
/** Files returned from fs.readdir(path, { withFileTypes: true }). */ | |
files: Dirent[]; | |
/** The current level we're operating on with -1 being the root. */ | |
level: number; | |
}; | |
/** | |
* Starting at a root directory, recursively walk every file and its sub-directories. | |
*/ | |
export async function getFiles( | |
/** Path to the root directory. */ | |
path: string, | |
/** Predicate for the current file or directory. Returning `null` will stop traversal. */ | |
predicate: (fileFormat: FileFormat) => any, | |
_level = -1, | |
_isDirectory = true | |
) { | |
const extension = extname(path).slice(1); | |
const name = basename(path, `.${extension}`); | |
let files = []; | |
let children = []; | |
if (_isDirectory) { | |
files = await fs.readdir(path, { withFileTypes: true }); | |
children = await Promise.all( | |
files.map((file) => | |
getFiles( | |
`${path}/${file.name}`, | |
predicate, | |
_level + 1, | |
file.isDirectory() | |
) | |
) | |
); | |
} | |
return predicate({ | |
type: _isDirectory ? 'directory' : 'file', | |
level: _level, | |
extension: extension === '' ? null : extension, | |
files: files.filter(Boolean), | |
children: children.filter(Boolean), | |
name, | |
path, | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment