首頁 >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