Computer scienceBackendNode.jsCore ConceptsInternal modulesFile system module

lstat, fstat and stat

8 minutes read

Imagine you're building a dynamic website with Node.js, serving various files to users from your server's file system. Whether it's images, documents, or web pages, it's crucial to understand each file's nature, size, and permissions, especially in a bustling platform where users constantly upload files.

In this topic, you'll learn about three pivotal Node.js functions: lstat, fstat, and stat. These functions are key to effectively navigating and interacting with the file system in your applications.

Retrieving file properties with fs.stat()

The fs.stat() function asynchronously retrieves information about a file or directory. It provides details such as file type, size, and permissions. This function follows symbolic links as it traverses the link and returns information about the target file or directory if the path points to a symbolic link.

This is the fs.stat() syntax:

fs.stat( path, options, callback )

Now let's take a look at a practical implementation of fs.stat():

const fs = require('fs');
  
// Getting information for a file
fs.stat("./files/readme.txt", (error, stats) => {
  if (error) {
    console.log(error);
  }
  else {
    console.log("Stats object for: readme.txt");
    console.log(stats);
  
    // Using methods of the Stats object
    console.log('File type:', stats.isFile() ? 'Regular File' : 'Not a Regular File');
    console.log("Path is file:", stats.isFile());
    console.log("Path is directory:", stats.isDirectory());
  }
});

In the above code snippet, fs.stat() retrieves details like file size, permissions, and timestamps from a file named "readme.txt". If there are no errors, fs.stat() returns a Stat object containing this information. We then log this object, offering a comprehensive view of the file's attributes.

It is important to understand what we mean by a regular file. In the context of file systems, a regular file is a file that contains any kind of data. This could be a text file, image file, binary file, or something else. Regular files are different from other types of files. For instance, directory files are not regular files. They are containers for other files. Similarly, symbolic links are not regular files either. They act as shortcuts or references to other files. There are also special files, such as device files, which are not considered regular files.

We use the isFile() method of the Stats object to determine whether "readme.txt" is a regular file or not. This method returns true for regular files and false for other types of files like directories or symbolic links. We also demonstrate how to distinguish between a file and a directory using the isFile() and isDirectory() methods. Here is the resulting information about the "readme.txt" file:

Getting information for a file

The fs.stat() function fetches information about a file. It follows symbolic links, providing information about the target file if the path points to a link. It's often useful when you want information about the actual file being pointed to.

The fs.lstat() function asynchronously retrieves fs.Stats information for a symbolic link or a file, without following the link if it points to another location. It provides details such as file type, size, and permissions.

This is the lstat syntax:

fs.lstat( path, options, callback )

Now let's take a look at a practical example where we use fs.lstat():

const fs = require("fs");
// /path/to/your/symlink
fs.symlinkSync("./myCv_file.txt", "./myCvsymlink", "file");
console.log("Symlink to file created");

fs.lstat("myCvsymlink", (err, stats) => {
  if (err) console.log(err);
  else {
    console.log("Stat of myCvsymlink");
    console.log(stats);
  }
});

We can inspect the properties of a symbolic link. Here "myCvsymlink" points to a file named "myCv_file.txt." Having a symbolic link is like creating a shortcut to a document on your computer. The fs.lstat() function inspects the properties of this link. It helps us determine whether "myCvsymlink" is a regular file or something else. It also allows us to retrieve information such as its size and permissions. If everything goes well, the code displays detailed information about the link, including its properties.

You can learn about fs.symlinkSync in the Node.js documentation. Here are the properties of the symbolic link "myCvsymlink".

My cv symbolic link properties

These properties include information about the link since we are calling lstat on a symbolic link. It retrieves information about the link itself and not the target file it points to. The information includes its size, permissions, timestamps (access time, modification time, etc), and more. However, it's important to note that some of these properties may not be relevant or meaningful for symbolic links.

For symbolic links, the most commonly used properties are:

  • size: The size of the symbolic link in bytes.
  • mode: The permissions of the symbolic link.
  • ctime (Change Time): The timestamp when the symbolic link's attributes were last changed.

Unlike fs.stat(), fs.lstat() does not follow the link to its target but provides information about the link itself.

Inspecting open file information with fs.fstat()

The fs.fstat() function asynchronously retrieves fs.Stats information for an open file using its file descriptor (fd). It provides details about the file's type, size, permissions, and more.

This is the fs.fstat() syntax:

fs.fstat(fd, options, callback)

Now let's take a look at a practical example of how fs.fstat() works:

const fs = require("fs");
// /path/to/your/file
const filePath = "./files/readme.txt";

// Open the file and get a file descriptor
const fileDescriptor = fs.openSync(filePath, "r");

fs.fstat(fileDescriptor, (err, stats) => {
  if (err) {
    console.error("Error:", err.message);
    return;
  }
  console.log(
    "File type:",
    stats.isFile() ? "Regular File" : "Not a Regular File"
  );
  console.log("File size:", stats.size, "bytes");
  console.log("File permissions:", stats.mode.toString(8));

  // Close the file descriptor when done
  fs.closeSync(fileDescriptor);
});

To inspect file metadata efficiently in Node.js, we define the file's path. In this case, the file's path is ./files/readme.txt which signifies its location relative to the current working directory. We open the file using fs.openSync() with read mode ('r') and obtain a file descriptor. The file descriptor allows us to interact with the file. With fs.fstat(), we gather metadata about the file, including its type, size in bytes, and permissions, within the callback function. Finally, we responsibly close the file descriptor with fs.closeSync() to ensure proper resource management.

Here are the results:

fs.Stats information for an open readme file

When working with file descriptors and fs.fstat(), it is essential to ensure that you properly open and close the file. This is where methods like fs.openSync() and fs.closeSync() come into play. fs.openSync() synchronously opens a file, returning a file descriptor that you can use with methods like fs.fstat(). After your work with the file is complete, use fs.closeSync() to close the file descriptor. This frees up system resources and prevents potential resource leaks. It's crucial to always close any file descriptors that you open to ensure the efficient use of system resources. You can get to know more about fs.openSync() and fs.closeSync() in the Node.js documentation.

Similar to fs.lstat(), fs.fstat() retrieves file information, but it operates on a file descriptor instead of a file path. This makes fs.fstat() particularly useful when working with streams and open files.

Key differences between fstat() and lstat()

1. Input Parameter:

  • fstat(): Requires a file descriptor fd as the input parameter. This file descriptor represents an open file.
  • lstat(): Takes a file or directory path as the input parameter. It operates on the file or directory specified by the given path.

2. Usage:

  • We typically use fstat() when a file is already open and we need to gather information about that specific file using its file descriptor. This is especially useful when working with streams or when you obtain a file descriptor from other file-related operations.
  • lstat() is used to retrieve information about a file or directory specified by a path. It is beneficial when there is a need to inspect symbolic links without following those links to their target.

3. Symbolic Links:

  • fstat() follows neither symbolic links nor resolves them. It provides information about the open file associated with the provided file descriptor, regardless of whether it's a symbolic link.
  • lstat() follows symbolic links. It retrieves information about the symbolic link itself and not the target it points to. If the path points to a symbolic link, lstat() provides details about the link, while fstat() provides information about the open file referred to by the file descriptor.

4. File Descriptor and Path:

  • fstat() operates on an open file through its file descriptor, making it suitable for examining open files directly.
  • lstat() operates on files or directories specified by their paths, allowing you to gather information about files or directories anywhere in the file system.

5. Resource Management:

  • When using fstat(), you should ensure that you properly open and close the file using functions like fs.open() and fs.close() to avoid resource leaks.
  • stat() does not involve file descriptor management, since it operates directly on paths.

The distinction between fstat() and lstat() lies in their input parameters, usage scenarios, and how they handle symbolic links. fstat() is used with file descriptors for open files and does not follow symbolic links, while lstat() operates on file paths and provides information about symbolic links themselves if encountered.

Conclusion

In this topic, you learned about the fs.lstat(), fs.fstat(), and fs.stat() functions. They are pivotal for discerning attributes about files and directories. Whether determining file types, accessing permissions, or understanding symbolic links, these functions allow you to make file systems operations using Node.js efficiently.

With this knowledge in hand, you're well-prepared to apply lstat, fstat, and stat functions in your Node.js projects. They will make your file system interactions more robust, precise, and efficient. As you continue your Node.js journey, remember the versatility these functions offer and the potential they unlock for your applications. Happy coding, and may your file interactions be seamless and productive!

Now let's go ahead and test our newly acquired knowledge with some theory and coding tasks!

7 learners liked this piece of theory. 0 didn't like it. What about you?
Report a typo