Deno 如何同步获取指定目录下所有文件?

您所在的位置:网站首页 node读取目录下所有文件 Deno 如何同步获取指定目录下所有文件?

Deno 如何同步获取指定目录下所有文件?

2024-05-09 14:07| 来源: 网络整理| 查看: 265

Deno 如何同步获取指定目录下所有文件?

By 晚晴幽草轩轩主

发表于 2021-03-01

倾城之链

在基于 Deno / Node.js 编写程序,时常会遇到类似这样的需求:“列出(遍历)目录下的所有文件,包括子目录“。如何实现这一点呢,很显然可以使用一些已写好的工具库,如 node-rd、node-walk、glob 等;但她们或多或少,都有些弊端,不方便使用;那么手动写一个方法,来实现“同步获取指定目录下所有文件“呢?本篇文章,即同大家一起探讨下这个问题。

Deno 如何同步获取指定目录下所有文件?

本文首发于个人最新博客Node.js 如何同步获取指定目录下所有文件? | 静轩之别苑。

如果要获得指定目录下文件,您可以使用 fs.readdir 或 fs.readdirSync 方法。fs 包含在 Node.js 核心中,因此无需安装任何软件。这非常简单,具体代码如下代码:

12345678910111213const fs = require('fs');const exampleFolder = './examples/';// 异步调用fs.readdir(exampleFolder, (err, files) => { files.forEach(file => { console.log(file); });});// 同步调用fs.readdirSync(exampleFolder).forEach(file => { console.log(file);});

但指定的目录下,除了文件,也可能存在文件夹,这就要求需要通过递归循环遍历:如果判定为文件夹,则继续往文件夹内部走,直到该目录只有文件,而没有文件夹才停止。只是一个目录,同步获取其内容,这很容易;但多重嵌套的文件夹(目录),因为不知道何时能遍历完毕,想同步拿到结果,传统的递归遍历,是不足以完成。这就需要借助已经使用非常高频的 async/await 函数。

下面是基于 Deno 以及 Node.js 的两种实现;原理相同,都是基于 TypeScript 编写;只不过调用 API 不同;考虑到以 Deno 语言编写方式,更方便运行,也是未来新趋势,就将其写在前面;您只需安装下 Deno,运行如下命令即可:

Deno 同步获取指定目录下所有文件1deno run --unstable --allow-net --allow-read deep-loop-travesal.ts 1234567891011121314151617181920212223242526272829303132/** * @desc 深度循环遍历,检索指定目录下所有 .js .ts 文件,并 push 到指定数组; * @param directory - 指定目录 * @param filePathArr - 指定数组 */import * as path from "https://deno.land/std/path/mod.ts";const deepLoopTraversal = async (directory: string, filePathArr: any[]) => { for await (const dirEntry of Deno.readDir(directory)) { const filename = dirEntry.name console.log(filename) const filePath = path.join(directory, filename); const stats = Deno.statSync(filePath); if (stats.isDirectory) { await deepLoopTraversal(filePath, filePathArr) } else { const isFile = stats.isFile; const extname = isFile ? path.extname(filePath) : ''; if (extname === '.js' || extname === '.ts') { filePathArr.push(filePath) } } }}const main = async () => { const filePathArr: Array = [] await deepLoopTraversal(Deno.cwd(), filePathArr) console.log(`您指定的目录下,是 .js 或 .ts 文件,有以下内容:`) console.log(filePathArr)}main()

这里有必要申明的是,此处的 for 循环遍历,是不能够使用 forEach 等方法的;这具体缘由,看下 forEach 的方法说明,就了然了:它接收第一个参数,是 callback,即便对它进行 async,但在外层,却是不知何里面是何时遍历完成,这就导致了不同步,从而引起问题。如果您想使用,可以看 StackoverFlow 上大家给出的一些办法:Using async/await with a forEach loop。

Node.js 同步获取指定目录下所有文件

以下为 Node.js 写法,启动用到了 fs-extra npm 依赖,需要手动安装下。

12345678910111213141516171819202122232425262728293031323334/** * @desc 深度循环遍历,检索指定目录下所有 .js .ts 文件,并 push 到指定数组; * @param directory - 指定目录 * @param filePathArr - 指定数组 */import * as path from 'path';const fse = require('fs-extra');const deepLoopTraversal = async (directory: string, filePathArr: any[]) => { const promiseList: Promise[] = []; const filesList = await fse.readdir(directory); for (let i = 0, len = filesList.length; i < len; i++) { const filename = filesList[i]; const filePath = path.join(directory, filename); const stats = await fse.stat(filePath); if (stats.isDirectory()) { await deepLoopTraversal(filePath, filePathArr); } else { const isFile = stats.isFile(); const extname = isFile ? path.extname(filePath) : ''; if (extname === '.js' || extname === '.ts') { filePathArr.push(filePath) } } }}const main = async () => { const filePathArr: Array = [] await deepLoopTraversal(process.cwd(), filePathArr) console.log(`您指定的目录下,是 .js 或 .ts 文件,有以下内容:`) console.log(filePathArr)}main() 实例说明

建造「测试目录」如下,对其进行运行如上脚本,将会得到什么结果呢?

1234567.├── a-dir│   ├── c-file.js│   └── d-dir│   └── e-file.js├── b-file.js└── deep-loop-travesal.ts

运行脚本,将得到如下结果(因为目录首字母、与文件首字母,决定了 readDir 得到的数组内容顺序,从而使得有以下结果):

123456[ ./~yun/a-dir/c-file.js", ./~yun/a-dir/d-dir/e-file.js", ./~yun/b-file.js", ./~yun/deep-loop-travesal.ts"] 问题思考

这里有个问题,需要思考下;上面所得到文件数组,顺序由每层文件名、文件夹名所决定。如果想要以从外至内的顺序,得到最终的结果数组,那么该如何处理呢?Promise.all 是解决这个问题的一剂良方。如果判定是文件夹,则将对它的递归循环,放置于一个数组(promiseList),后面将该数组传递给 Promise.all 方法予以调用,问题迎刃而解(目录中内容,将会延迟遍历)。

Promise.all() 方法接收一个 promise 的 iterable 类型(注:Array,Map,Set 都属于 ES6 的 iterable 类型)的输入,并且只返回一个 Promise 实例, 那个输入的所有 promise 的 resolve 回调的结果是一个数组。这个 Promise 的 resolve 回调执行是在所有输入的 promise 的 resolve 回调都结束,或者输入的 iterable 里没有 promise 了的时候。它的 reject 回调执行是,只要任何一个输入的 promise 的 reject 回调执行或者输入不合法的 promise 就会立即抛出错误,并且 reject 的是第一个抛出的错误信息。

123456789101112131415161718192021222324252627282930313233343536/** * @file deep-loop-travesal.ts * @desc 深度循环遍历,检索指定目录下所有 .js .ts 文件,并 push 到指定数组; * @param directory - 指定目录 * @param filePathArr - 指定数组 */import * as path from "https://deno.land/std/path/mod.ts";const deepLoopTraversal = async (directory: string, filePathArr: any[]) => { const promiseList: Promise[] = []; for await (const dirEntry of Deno.readDir(directory)) { const filename = dirEntry.name const filePath = path.join(directory, filename); const stats = Deno.statSync(filePath); if (stats.isDirectory) { promiseList.push(deepLoopTraversal(filePath, filePathArr)); } else { const isFile = stats.isFile; const extname = isFile ? path.extname(filePath) : ''; if (extname === '.js' || extname === '.ts') { filePathArr.push(filePath) } } } if (promiseList.length) { await Promise.all(promiseList); }}const main = async () => { const filePathArr: Array = [] await deepLoopTraversal(Deno.cwd(), filePathArr) console.log(`您指定的目录下,是 .js 或 .ts 文件,有以下内容:`) console.log(filePathArr)}main()

依旧是上面的「测试目录」,运行如上改造后的脚本,将得到如下结果,结果符合预期;

123456[ ~/yun/b-file.js", ~/yun/deep-loop-travesal.ts", ~/yun/a-dir/c-file.js", ~/yun/a-dir/d-dir/e-file.js"]

以上,便是关于“Node.js/Deno,如何同步获取指定目录下所有文件“问题的一点,如有谬误,欢请斧正。

倾城之链作为一个开放平台,旨在云集全球优秀网站,探索互联网中更广阔的世界;在这里,你可以轻松发现、学习、分享更多有用或有趣的事物。

小程序码 - 倾城之链

您可能感兴趣的文章 基于 python 对文本做分词、生成词云图 如何为不同应用窗口,自动切换不同输入法 为文章图片添加外阴影效果 Markdown 用法中的奇技淫巧 关于 CSS 预处理器:Sass Vs Dart Sass JavaScript 之 import export Vs require module.exports 前端利器之 npx 使用纪要 前端项目开发规范意见 前端开发与 DevOps 实践 静晴轩 ~ 晚晴幽草轩 个人微信公众号:晚晴幽草轩;名字取自:“天意怜幽草,人间重晚晴”。专注互联网开发(Web 大前端、快应用、小程序),以及分享优质网站、AI 应用、效率工具、心得感悟等内容。 文档信息 版权声明:知识共享署名-非商业性使用-禁止演绎(创意共享3.0许可证) 文章出处:晚晴幽草轩 发表日期:2021-03-01 社交媒体: Front-End DenoNode.jsTypeScript


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3