首页 >web前端 >js教程 >在DENO中使用文件系统

在DENO中使用文件系统

Jennifer Aniston
Jennifer Aniston原创
2025-02-09 09:43:10894浏览

Working with the File System in Deno

本文将深入探讨Deno,并创建一个命令行工具,用于在文件和文件夹中搜索文本。我们将使用Deno提供的各种API方法来读取和写入文件系统。

上一篇文章中,我们使用Deno构建了一个命令行工具,用于向第三方API发出请求。本文中,我们将暂时忽略网络操作,构建一个工具,允许您在当前目录内的文件和文件夹中搜索文本——类似于grep之类的工具。

注意:我们构建的工具不会像grep那样优化和高效,我们也并非旨在取代它!构建这样一个工具的目的是为了熟悉Deno的文件系统API。

关键要点

  • Deno的文件系统API有助于创建用于在文件和目录中搜索文本的命令行工具,类似于grep工具,但没有那么优化。
  • 在Deno中使用Yargs,开发人员可以为命令行应用程序构建用户界面,从而能够在指定的目录中进行文本搜索。
  • Deno提供内置函数,如Deno.readDir用于列出文件和Deno.readTextFile用于读取文件内容,从而简化文件系统交互,无需额外导入。
  • 可以使用Deno的path模块高效地管理文件路径,该模块包括path.join等函数,用于连接文件路径。
  • Deno脚本需要显式的权限标志,如–allow-read–allow-write才能执行文件系统操作,通过控制脚本功能来增强安全性。
  • 开发人员可以使用deno compile将Deno脚本编译成独立的可执行文件,通过封装必要的权限来简化分发和执行。

安装Deno

我们假设您已经在本地机器上运行了Deno。您可以查看Deno网站或上一篇文章,以获取更详细的安装说明,以及如何为您的编辑器添加Deno支持的信息。

在撰写本文时,Deno的最新稳定版本是1.10.2,这就是我在本文中使用的版本。

作为参考,您可以在GitHub上找到本文的完整代码。

使用Yargs设置新的命令

与上一篇文章一样,我们将使用Yargs来构建用户可以用来执行我们工具的界面。让我们创建index.ts并用以下内容填充它:

<code class="language-typescript">import yargs from "https://deno.land/x/yargs@v17.0.1-deno/deno.ts";

interface Yargs<argvreturntype></argvreturntype> {
  describe: (param: string, description: string) => Yargs<argvreturntype>;
</argvreturntype>  demandOption: (required: string[]) => Yargs<argvreturntype>;
</argvreturntype>  argv: ArgvReturnType;
}

interface UserArguments {
  text: string;
}

const userArguments: UserArguments =
  (yargs(Deno.args) as unknown as Yargs<userarguments>)
</userarguments>    .describe("text", "the text to search for within the current directory")
    .demandOption(["text"])
    .argv;

console.log(userArguments);
</code>

这里有很多值得指出的内容:

  • 我们通过指向Deno存储库中的路径来安装Yargs。我明确使用精确的版本号来确保我们始终获得该版本,这样我们就不会在脚本运行时使用任何最新的版本。
  • 在撰写本文时,Deno TypeScript对Yargs的体验并不好,所以我创建了自己的接口并使用它来提供一些类型安全性。
  • UserArguments包含我们将向用户索取的所有输入。目前,我们只要求输入文本,但将来我们可以将其扩展为提供要搜索的文件列表,而不是假设当前目录。

我们可以使用deno run index.ts运行它并查看我们的Yargs输出:

<code class="language-typescript">import yargs from "https://deno.land/x/yargs@v17.0.1-deno/deno.ts";

interface Yargs<argvreturntype></argvreturntype> {
  describe: (param: string, description: string) => Yargs<argvreturntype>;
</argvreturntype>  demandOption: (required: string[]) => Yargs<argvreturntype>;
</argvreturntype>  argv: ArgvReturnType;
}

interface UserArguments {
  text: string;
}

const userArguments: UserArguments =
  (yargs(Deno.args) as unknown as Yargs<userarguments>)
</userarguments>    .describe("text", "the text to search for within the current directory")
    .demandOption(["text"])
    .argv;

console.log(userArguments);
</code>

现在是时候开始实现了!

列出文件

在我们开始搜索给定文件中的文本之前,我们需要生成一个要搜索的目录和文件列表。Deno提供Deno.readdir,它是“内置”库的一部分,这意味着您不必导入它。它在全局命名空间中可用。

Deno.readdir是异步的,并返回当前目录中文件和文件夹的列表。它将这些项目作为AsyncIterator返回,这意味着我们必须使用for await ... of循环来获取结果:

<code class="language-bash">$ deno run index.ts
Check file:///home/jack/git/deno-file-search/index.ts
Options:
  --help     Show help                                                 [boolean]
  --version  Show version number                                       [boolean]
  --text     the text to search for within the current directory      [required]

Missing required argument: text</code>

这段代码将从当前工作目录(Deno.cwd()提供)读取并记录每个结果。但是,如果您现在尝试运行脚本,您将收到错误:

<code class="language-typescript">for await (const fileOrFolder of Deno.readDir(Deno.cwd())) {
  console.log(fileOrFolder);
}
</code>

请记住,Deno要求所有脚本都明确地获得从文件系统读取的权限。在我们的例子中,--allow-read标志将使我们的代码能够运行:

<code class="language-bash">$ deno run index.ts --text='foo'
error: Uncaught PermissionDenied: Requires read access to <cwd>, run again with the --allow-read flag
</cwd>for await (const fileOrFolder of Deno.readDir(Deno.cwd())) {
                                                   ^
    at deno:core/core.js:86:46
    at unwrapOpResult (deno:core/core.js:106:13)
    at Object.opSync (deno:core/core.js:120:12)
    at Object.cwd (deno:runtime/js/30_fs.js:57:17)
    at file:///home/jack/git/deno-file-search/index.ts:19:52</code>

在本例中,我在构建工具的目录中运行脚本,因此它找到了TS源代码、.git存储库和.vscode文件夹。让我们开始编写一些函数来递归地导航此结构,因为我们需要找到目录中的所有文件,而不仅仅是顶级文件。此外,我们可以添加一些常见的忽略项。我认为没有人会希望脚本搜索整个.git文件夹!

在下面的代码中,我们创建了getFilesList函数,它接受一个目录并返回该目录中的所有文件。如果遇到目录,它将递归调用自身以查找任何嵌套的文件,并返回结果:

<code class="language-bash">~/$ deno run --allow-read index.ts --text='foo'
{ name: ".git", isFile: false, isDirectory: true, isSymlink: false }
{ name: ".vscode", isFile: false, isDirectory: true, isSymlink: false }
{ name: "index.ts", isFile: true, isDirectory: false, isSymlink: false }
</code>

然后我们可以像这样使用它:

<code class="language-typescript">const IGNORED_DIRECTORIES = new Set([".git"]);

async function getFilesList(
  directory: string,
): Promise<string> {
  const foundFiles: string[] = [];
  for await (const fileOrFolder of Deno.readDir(directory)) {
    if (fileOrFolder.isDirectory) {
      if (IGNORED_DIRECTORIES.has(fileOrFolder.name)) {
        // Skip this folder, it's in the ignore list.
        continue;
      }
      // If it's not ignored, recurse and search this folder for files.
      const nestedFiles = await getFilesList(
        path.join(directory, fileOrFolder.name),
      );
      foundFiles.push(...nestedFiles);
    } else {
      // We found a file, so store it.
      foundFiles.push(path.join(directory, fileOrFolder.name));
    }
  }
  return foundFiles;
}
</string></code>

我们还得到一些看起来不错的输出:

<code class="language-typescript">const files = await getFilesList(Deno.cwd());
console.log(files);
</code>

使用path模块

我们现在可以使用模板字符串组合文件路径,如下所示:

<code class="language-bash">$ deno run --allow-read index.ts --text='foo'
[
  "/home/jack/git/deno-file-search/.vscode/settings.json",
  "/home/jack/git/deno-file-search/index.ts"
]
</code>

但这使用Deno的path模块会更好。此模块是Deno作为其标准库一部分提供的模块之一(与Node使用其path模块非常相似),如果您使用过Node的path模块,则代码看起来非常相似。在撰写本文时,Deno提供的最新标准库版本是0.97.0,我们从mod.ts文件导入path模块:

<code class="language-typescript">import yargs from "https://deno.land/x/yargs@v17.0.1-deno/deno.ts";

interface Yargs<argvreturntype></argvreturntype> {
  describe: (param: string, description: string) => Yargs<argvreturntype>;
</argvreturntype>  demandOption: (required: string[]) => Yargs<argvreturntype>;
</argvreturntype>  argv: ArgvReturnType;
}

interface UserArguments {
  text: string;
}

const userArguments: UserArguments =
  (yargs(Deno.args) as unknown as Yargs<userarguments>)
</userarguments>    .describe("text", "the text to search for within the current directory")
    .demandOption(["text"])
    .argv;

console.log(userArguments);
</code>

mod.ts在导入Deno的标准模块时始终是入口点。此模块的文档位于Deno网站上,并列出了path.join,它将接受多个路径并将它们连接成一个路径。让我们导入并使用该函数,而不是手动组合它们:

...(此处省略了其余代码,因为与原文重复,并且已经在上一个输出中进行了修改和优化。)

...(The rest of the code is omitted because it's repetitive from the original and has already been modified and optimized in the previous output.)

以上是在DENO中使用文件系统的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn