How can one check if a file or directory exists using Deno?
Asked Answered
O

5

37

The Deno TypeScript runtime has built-in functions, but none of them address checking the existence of a file or directory. How can one check if a file or directory exists?

Ophiology answered 18/6, 2019 at 23:4 Comment(1)
The deprecation of exists has been undone. Please check my answer for important details.Bioastronautics
S
26

There is the standard library implementation, here: https://deno.land/std/fs/mod.ts

import {existsSync} from "https://deno.land/std/fs/mod.ts";

const pathFound = existsSync(filePath)
console.log(pathFound)

This code will print true if the path exists and false if not.

And this is the async implementation:

import {exists} from "https://deno.land/std/fs/mod.ts"

exists(filePath).then((result : boolean) => console.log(result))

Make sure you run deno with the unstable flag and grant access to that file:

deno run --unstable  --allow-read={filePath} index.ts
Safeconduct answered 10/8, 2020 at 19:8 Comment(2)
exists and existsSync have been removed in the latest std library in favour of trying to read the file and handling the error if it doesn't exists. See @BentoumiTech answer below and this comment in the Deno repo which was adopted github.com/denoland/deno_std/issues/1216#issuecomment-937722077Appeasement
@Appeasement Now, the deprecation of exists has been undone with some changes. Please check my answer for details.Bioastronautics
B
26

The Deno API changed since the release of Deno 1.0.0. If the file is not found the exception raised is Deno.errors.NotFound

const exists = async (filename: string): Promise<boolean> => {
  try {
    await Deno.stat(filename);
    // successful, file or directory must exist
    return true;
  } catch (error) {
    if (error instanceof Deno.errors.NotFound) {
      // file or directory does not exist
      return false;
    } else {
      // unexpected error, maybe permissions, pass it along
      throw error;
    }
  }
};

exists("test.ts").then(result =>
  console.log("does it exist?", result)); // true

exists("not-exist").then(result =>
  console.log("does it exist?", result)); // false

As the original answer account is suspended and cannot change his answer if I comment on it, I'm reposting a fixed code snippet.

Biopsy answered 18/5, 2020 at 11:40 Comment(0)
S
26

There is the standard library implementation, here: https://deno.land/std/fs/mod.ts

import {existsSync} from "https://deno.land/std/fs/mod.ts";

const pathFound = existsSync(filePath)
console.log(pathFound)

This code will print true if the path exists and false if not.

And this is the async implementation:

import {exists} from "https://deno.land/std/fs/mod.ts"

exists(filePath).then((result : boolean) => console.log(result))

Make sure you run deno with the unstable flag and grant access to that file:

deno run --unstable  --allow-read={filePath} index.ts
Safeconduct answered 10/8, 2020 at 19:8 Comment(2)
exists and existsSync have been removed in the latest std library in favour of trying to read the file and handling the error if it doesn't exists. See @BentoumiTech answer below and this comment in the Deno repo which was adopted github.com/denoland/deno_std/issues/1216#issuecomment-937722077Appeasement
@Appeasement Now, the deprecation of exists has been undone with some changes. Please check my answer for details.Bioastronautics
M
6

There is no function that's specifically for checking if a file or directory exists, but the Deno.stat function, which returns metadata about a path, can be used for this purpose by checking the potential errors against Deno.ErrorKind.NotFound.

const exists = async (filename: string): Promise<boolean> => {
  try {
    await Deno.stat(filename);
    // successful, file or directory must exist
    return true;
  } catch (error) {
    if (error && error.kind === Deno.ErrorKind.NotFound) {
      // file or directory does not exist
      return false;
    } else {
      // unexpected error, maybe permissions, pass it along
      throw error;
    }
  }
};

exists("test.ts").then(result =>
  console.log("does it exist?", result)); // true

exists("not-exist").then(result =>
  console.log("does it exist?", result)); // false
Mendel answered 25/7, 2019 at 16:21 Comment(0)
B
4

The deprecation of exists has been undone in 0.182.0, since there are too many valid use cases, however you should avoid it as good as possible, because it potentially causes race conditions in your code, meaning your file or directory shall be tempered by a third party after checking for its existence, since exists won't lock the file or directory.

For instance: If you want to remove a file only if it exists, instead of doing:

import { exists } from "https://deno.land/std/fs/mod.ts";

if (await exists("./foo")) {
  await Deno.remove("./foo");
}

You should rather do:

try {
  await Deno.remove("./foo");
} catch (error) {
  if (!(error instanceof Deno.errors.NotFound)) {
    throw error;
  }
  // Do nothing...
}

Same goes to editing files. If you are going to work with your file, just try to open/edit it and catch the exception.

However, there are valid use cases for exists, such as checking if a file or directory exists for a third party tool and skipping to launch the tool if it's missing. This can be very handy, if the tool is expensive to launch or fails to report a proper error message on a wrong path.

But there were problems with the former exists:

  • Firstly, there was the pitfall in which you shall check for a directory and exists would return true, but it was a file with the same name that was found at the destination, leading to follow-up errors.
  • Secondly, exists would return false if the file cannot be read only on Windows, but not on POSIX systems, because its underlying lstat call would still succeed on POSIX systems, despite the path being not readable by the user.

The new implementation solves all those issues and provides options that you certainly should make use of, if you really have to use exists:

import { exists } from "https://deno.land/std/fs/mod.ts";
const fooDirExistsAndIsReadable = await exists("./foo", {
  isReadable: true, // check if foo can be read on POSIX and Windows
  isDirectory: true // check if foo is a directory
});
const barFileExistsAndIsReadable = await exists("./bar", {
  isReadable: true, // check if bar can be read on POSIX and Windows
  isFile: true // check if bar is a file
});

Other than that, you can still use the implementation like before:

const foobarExists = await exists("./foobar");

It is important to know that exists uses stat instead of lstat now, meaning it now follows symlinks to make the options work as expected.

Disclaimer: I contributed the implementation to Deno after a fairly long discussion with a long back and forth and overthinking between all parties. I'm glad we made it, eventually.

Bioastronautics answered 16/11, 2022 at 12:5 Comment(0)
C
3

The exists function is actually part of the std/fs module although it is currently flagged as unstable. That means you need to deno run --unstable: https://deno.land/std/fs/README.md#exists

Curbing answered 26/5, 2020 at 7:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.