Flutter - Get List of Files/Directories in a Directory

This tutorial shows you how to get the list of files and directories inside a directory, including if there are nested sub directories.

If you want to get the list of entries inside a directory programmatically using Deno, there are already built-in functions that simplify the process. Below are the functions along with the usage examples and error handling.

Get List of Files and Directories

In Deno, you can easily get the list of files and directories using Deno.readDir or Deno.readDirSync. In order for the functions to work, you need to add --allow-read flag in deno run command since Deno needs read permission in order to read directories.

For this tutorial, let's assume there is a folder named data in the current working directory. Below is the structure of the folder.

  data
    data1
      file3.txt
    file1.txt
    file2.txt

Using Deno.readDir

Deno.readDir is a function for reading a directory with the given path.

  function Deno.readDir(path: string | URL): AsyncIterable<DirEntry>

You need to pass the path to the directory, either relative or absolute. If you pass an absolute path, it must be relative to the current working directory which defaults to the location where you execute deno run command. The working directory can be changed using Deno.chdir command.

The function returns an async iterable of DirEntry. DirEntry itself has the following fields.

  • string name: The file name.
  • boolean isFile: Whether the entry is a file.
  • boolean isDirectory: Whether the entry is a directory.
  • boolean isSymlink: Whether the entry is a symlink.

To get the result, you need to iterate over the iterable. Below is the usage example.

  for await (const dirEntry of Deno.readDir('data')) {
    console.log(dirEntry);
  }
  { name: "data1", isFile: false, isDirectory: true, isSymlink: false }
  { name: "file1.txt", isFile: true, isDirectory: false, isSymlink: false }
  { name: "file2.txt", isFile: true, isDirectory: false, isSymlink: false }

Get List of Files

The above example returns all entries including files and directories. To get the list of file names, you can filter entries whose value of isFile field is true.

  const fileNames: string[] = [];
  
  for await (const dirEntry of Deno.readDir('data')) {
    if (dirEntry.isFile) {
      fileNames.push(dirEntry.name);
    }
  }
  
  console.log(fileNames);

Output:

  [ "file1.txt", "file2.txt" ]

Get List of Directories

To get the list of directory names, you can filter entries whose value of isDirectory field is true.

  const dirNames: string[] = [];
  
  for await (const dirEntry of Deno.readDir('data')) {
    if (dirEntry.isDirectory) {
      dirNames.push(dirEntry.name);
    }
  }
  
  console.log(dirNames);

Output:

  [ "data1" ]

Get List in Nested Sub Directories

The Deno.readDir command only lists the entries in the current directories, but not including the entries in sub directories. To get the list of files and directories in nested sub directories, you can do it recursively like the code below.

  async function getNames(currentPath: string) {
    const names: string[] = [];
  
    for await (const dirEntry of Deno.readDir(currentPath)) {
      const entryPath = `${currentPath}/${dirEntry.name}`;
      names.push(entryPath);
  
      if (dirEntry.isDirectory) {
        names.push(await getNames(entryPath));
      }
    }
  
    return names;
  }
  
  console.log(await getNames('data'));

Output:

  [ "data/data1", "data/file1.txt", "data/file2.txt" ]

Using Deno.readDirSync

Deno.readDir is similar to Deno.readDir, but it performs the operation synchronously. It returns an iterable whose element type is also DirEntry. If you want to filter files/directories only or get the list of entries in nested sub directories, you can use the above examples of readDir as references.

  function Deno.readDirSync(path: string | URL): Iterable<DirEntry>

Below is the usage example.

  for (const dirEntry of Deno.readDirSync('data')) {
    console.log(dirEntry);
  }

Error Handling

There are things that may cause an error. For example if the passed path doesn't exist.

  Check file:///home/ivan/Projects/deno/src/examples/dir_list.ts
  error: Uncaught (in promise) NotFound: No such file or directory (os error 2)
    at processResponse (core.js:223:11)
    at Object.jsonOpAsync (core.js:240:12)
    at async Object.[Symbol.asyncIterator] (deno:cli/rt/30_fs.js:125:16)
    at async file:///home/ivan/Projects/deno/src/examples/dir_list.ts:1:18

Another cause of error is passing a path that's not a directory.

  Check file:///home/ivan/Projects/deno/src/examples/dir_list.ts
  error: Uncaught (in promise) Error: Not a directory (os error 20)
      at processResponse (core.js:223:11)
      at Object.jsonOpAsync (core.js:240:12)
      at async Object.[Symbol.asyncIterator] (deno:cli/rt/30_fs.js:125:16)
      at async file:///home/ivan/Projects/deno/src/examples/dir_list.ts:1:18

Or if the user that runs the application doesn't have sufficient permission to access a directory.

  Check file:///home/ivan/Projects/deno/src/examples/dir_list.ts
  error: Uncaught (in promise) PermissionDenied: Permission denied (os error 13)
      at processResponse (core.js:223:11)
      at Object.jsonOpAsync (core.js:240:12)
      at async Object.[Symbol.asyncIterator] (deno:cli/rt/30_fs.js:125:16)
      at async file:///home/ivan/Projects/deno/src/examples/dir_list.ts:1:18

You can wrap the code inside a try-catch block to handle any error that can be thrown while trying to read a directory.

  try {
    for await (const dirEntry of Deno.readDir('x')) {
      console.log(dirEntry);
    }
  } catch (err) {
    console.error(err);
  }

Related Posts: