Amani
Amani

Reputation: 18153

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

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?

Upvotes: 39

Views: 15426

Answers (5)

Martin Braun
Martin Braun

Reputation: 12619

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.

Upvotes: 5

yonBav
yonBav

Reputation: 1915

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

Upvotes: 27

schlicki
schlicki

Reputation: 374

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

Upvotes: 3

BentoumiTech
BentoumiTech

Reputation: 1683

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.

Upvotes: 26

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

Upvotes: 6

Related Questions