Categories
JavaScript Nodejs

Node.js FS Module — Changing Ownership and Copying Files

Spread the love

Manipulating files and directories are basic operations for any program. Since Node.js is a server-side platform and can interact with the computer that it’s running on directly, being able to manipulate files is a basic feature.

Fortunately, Node.js has an fs module built into its library. It has many functions that can help with manipulating files and folders. File and directory operations that are supported include basic ones like manipulating and opening files in directories.

Likewise, it can do the same for files. It can do this both synchronously and asynchronously. It has an asynchronous API that has functions that support promises.

Also, it can show statistics for a file. Almost all file operations that we can think of can be done with the built-in fs module.

In this article, we will change ownership of a file with the chown function and copy files with the copyFile function.


Changing File Ownership With the fs.chown and fs.chownSync Functions

The chown function lets us change the ownership of a file asynchronously. It takes four arguments.

  1. The first argument is the path object which can be in the form of a string, a Buffer object, or a URL object.
  2. The second argument is the UID, which is the user ID of the user.
  3. The third argument is the GID, which is the group ID.
  4. The fourth argument is a callback function that has an err parameter which is null if the chown operation is successful, otherwise err will be an error object. The callback function is called when the chown operation is finished, whether it’s successful or not.

To use the chown function, we can write something like the following code:

In the example above, we change the ownership of the file file.txt to the user with UID 1000 and group with GID 1000. To find out the UID and GID of the user and group of the current user in Linux systems, we can use the id command.

The chown function has a synchronous version called chownSync. It takes three arguments.

  1. The first argument is the path object which can be in the form of a string, a Buffer object, or a URL object.
  2. The second argument is the UID, which is the user ID of the user.
  3. The third argument is the GID, which is the group ID. It returns undefined.

We can use it as in the following code:

const fs = require("fs");  
const file = "./files/file.txt";
fs.chownSync(file, 1000, 1000);  
console.log("File ownership changed");

It does the same thing as chown, but does it synchronously. If we just want to do the chown operation sequentially, we don’t have to use chown, a better alternative is to use the promise version of the chown function.

The promise version of the chown function takes three arguments.

  1. The first argument is the path object which can be in the form of a string, a Buffer object, or a URL object.
  2. The second argument is the UID, which is the user ID of the user.
  3. The third argument is the GID, which is the group ID. It returns a promise that resolves with no arguments when the chown operation is successfully done.

We can use it as in the following code:

To confirm that the chown worked as we expected, we can run the following commands in Linux systems. One way is to run ls -l , as in the command below:

ls -l ./files/file.txt

We can also use the stat command.

For example, we can run stat ./files/file.txt to get the ownership information of ./files/file.txt from the Uid and Gid output. With the stat command, we should get output that looks something like this:

File: './files/file.txt'  
  Size: 16              Blocks: 0          IO Block: 512    regular file  
Device: eh/14d  Inode: 22799473115106242  Links: 1  
Access: (0555/-r-xr-xr-x)  Uid: ( 1000/hauyeung)   Gid: ( 1000/hauyeung)  
Access: 2019-11-02 12:26:47.996290200 -0700  
Modify: 2019-11-02 12:26:47.996290200 -0700  
Change: 2019-11-02 12:44:45.037581600 -0700  
 Birth: -

Also, we can filter out the information we don’t need and just get the UID and GID with the "%U %G" format sequence. For example, we can run stat -c “%U %G” ./files/file.txt to get the UID and GID only for file.txt.


Copy Files With fs.copyFile and fs.copyFileSync

To copy files in a Node.js program, we can use the copyFile function. The copyfile function takes four arguments.

  1. The first argument is the path of the source file, which can be a string, a Buffer object, or a URL object.
  2. The second argument is the path of the destination file, which can also be a string, a Buffer object, or a URL object.
  3. The third argument is a numeric flag argument that specifies the behavior of the copy operation. The default value of the flag is 0.

The flag can be one of the following values or a bitwise combination of them:

  • fs.constants.COPYFILE_EXCL — The copy operation will fail if the destination file already exists.
  • fs.constants.COPYFILE_FICLONE — The copy operation will attempt to create a copy-on-write reflink. Copy-on-write means that if a file is copied but not modified then it will just reference the original file. The only time that it will do the actual copy is when we first write to a file. If the platform does not support copy-on-write, then a fallback copy mechanism is used.
  • fs.constants.COPYFILE_FICLONE_FORCE — The copy operation will attempt to create a copy-on-write reflink. If the platform does not support copy-on-write, then the operation will fail.

We can combine the constants above with the bitwise OR operator, for example like fs.constants.COPYFILE_EXCL | fs.constants.COPYFILE_FICLONE.

4. The fourth argument is a callback function that is called when the file copy operation is complete. It has an err parameter which is null when the copy file operation succeeded and an object with the error information otherwise.

There’s no guarantee of the atomicity of the copy operation. If an error occurs after the destination file is opened for writing, then Node.js will attempt to remove the destination.

By default, if no flags are set, the destination file will overwrite the existing file with the same name in the same location if it exists.

To use the copyFile function, we can write something like the following code:

In the code above, we set the source of the source file to be file.txt, the destination file to be fileCopy.txt.

Also, we specified that the copy operation will fail if the file exists with the fs.constants.COPYFILE_EXCL constant and we specify that the copy file operation will be done via the copy-on-write method with the fs.constants.COPYFILE_FICLONE flag.

The synchronous version of the copyFile function is the copyFileSync function. It takes the same arguments as the copyFile function except the callback.

  1. The first argument is the path of the source file, which can be a string, a Buffer object, or a URL object.
  2. The second argument is the path of the destination file, which can also be a string, a Buffer object, or a URL object.
  3. The third argument is a numeric flag argument that specifies the behavior of the copy operation. The default value of the flag is 0. The flags are the same ones as the copyFile function, and we can also combine them the same way.

There’s no guarantee of the atomicity of the copy operation. If an error occurs after the destination file is opened for writing, then Node.js will attempt to remove the destination.

By default, if no flags are set, the destination file will overwrite the existing file with the same name in the same location if it exists.

To use the copyFileSync function, we can write some code like the following example:

In the code above, we set the source of the source file to be file.txt, the destination file to be fileCopy.txt.

Also, we specified that the copy operation will fail if the file exists with the fs.constants.COPYFILE_EXCL constant and we specify that the copy file operation will be done via the copy-on-write method with the fs.constants.COPYFILE_FICLONE flag.

We catch any exceptions that are thrown by surrounding the code with the try...catch block.

There’s also a promise version of the copyFile function. It asynchronously copies the file from the source to the destination.

  1. The first argument is the path of the source file, which can be a string, a Buffer object, or a URL object.
  2. The second argument is the path of the destination file, which can also be a string, a Buffer object, or a URL object.
  3. The third argument is a numeric flag argument that specifies the behavior of the copy operation. The default value of the flag is 0. The flags are the same ones as the copyFile function, and we can combine them the same way.

There’s no guarantee of the atomicity of the copy operation. If an error occurs after the destination file is opened for writing, then Node.js will attempt to remove the destination.

By default, if no flags are set, the destination file will overwrite the existing file with the same name in the same location if it exists.

The promise version of copyFile resolves with no argument if the copy operation is successful.

We can use the promise of copyFile as in the following code:

In the code above, we set the source of the source file to be file.txt, the destination file to be fileCopy.txt.

Also, we specified that the copy operation will fail if the file exists with the fs.constants.COPYFILE_EXCL constant and we specify that the copy file operation will be done via the copy-on-write method with the fs.constants.COPYFILE_FICLONE flag.

We catch any exceptions that are thrown by using surround the code with the try...catch block.


Conclusion

With the chown function, we can change the ownership of a file. There are two asynchronous versions of the function, one is the regular asynchronous version and one is the promise version.

There’s also one synchronous version of the chown function, which is the chownSync function. They both change the owner by passing in the UID and GID of the user of your choice. UID is the user ID and GID is the group ID. We can copy files with the copyFile function.

There are two asynchronous versions of the copyFile function, one is the regular asynchronous version and one is the promise version.

There’s also a synchronous version of the copyFile function called the copyFileSync function. We can change how files are copied with flags that are available as constants in the fs module.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *