Node.js FS模块—重命名项目和删除目录

发布于1/18/2020 来自:「前端知否」微信公众号

操纵文件和目录是任何程序的基本操作。 由于Node.js是服务器端平台,并且可以直接与其运行的计算机进行交互,因此能够操作文件是一项基本功能。

幸运的是,Node.js的库中内置了一个fs模块。 它具有许多功能,可以帮助处理文件和文件夹。 支持的文件和目录操作包括基本操作,例如在目录中操作和打开文件。 同样,它可以对文件执行相同的操作。 它可以同步和异步执行此操作。 它具有异步API,该API具有支持promise的功能。 它还可以显示文件的统计信息。 我们可以想到的几乎所有文件操作都可以通过内置的fs模块完成。 在本文中,我们将使用rename函数系列重命名磁盘上存储的项目,并使用rmdir函数集合删除目录。

使用fs.rename和fs.renameSync重命名项目

要重命名存储在Node.js程序中磁盘上的项目,我们可以异步调用重命名函数。 它需要3个参数。 第一个参数是文件的旧路径。 可以是字符串,Buffer对象或URL对象。

第二个参数是文件的新路径,它也可以是字符串,Buffer对象或URL对象。

最后一个参数是在项目重命名操作结束时调用的回调函数。 如果重命名操作以错误结束,则回调函数采用err参数,该参数具有错误数据,否则err对象为null。

重命名之前,原始文件必须存在。 如果您要重命名的项目的路径已经存在,则该项目将被覆盖。 如果目标路径是目录,则将引发错误。

例如,我们可以像下面的代码一样使用它:

const fs = require("fs");

const sourceFile = "./files/originalFile.txt";

const destFile = "./files/renamedFile.txt";

fs.rename(sourceFile, destFile, err => {
if (err) throw err;
console.log("Rename complete!");
});

我们可以对目录执行相同的操作:

const fs = require("fs");

const oldDirectory = "./files/oldFolder";

const newDirectory = "./files/newFolder";

fs.rename(oldDirectory, newDirectory, err => {
if (err) throw err;
console.log("Directory rename complete!");
});

重命名功能的同步版本renameSync功能。 它采用与重命名相同的参数,但没有回调。 第一个参数是文件的旧路径。 可以是字符串,Buffer对象或URL对象。 第二个参数是文件的新路径,它也可以是字符串,Buffer对象或URL对象。 返回undefined

例如,我们可以像下面的代码那样使用renameSync函数来重命名文件:

const fs = require("fs");

const sourceFile = "./files/originalFile.txt";

const destFile = "./files/renamedFile.txt";

try {
fs.renameSync(sourceFile, destFile);
console.log("Rename complete!");
} catch (error) {
console.log(error);
}

重命名功能还有一个Promise版本,它也可以异步执行重命名操作。 它需要2个参数。

第一个参数是文件的旧路径。 可以是字符串,Buffer对象或URL对象。

第二个参数是文件的新路径,它也可以是字符串,Buffer对象或URL对象。 重命名函数的promise版本将返回一个promise,重命名操作成功时,会执行resolve,没有参数。 例如:

const fsPromises = require("fs").promises;

const sourceFile = "./files/originalFile.txt";

const destFile = "./files/renamedFile.txt";

(async () => {
try {
await fsPromises.rename(sourceFile, destFile);
console.log("Rename complete!");
} catch (error) {
console.log(error);
}
})();

对于需要顺序执行的操作,这种方式比renameSync更好,因为像Promise这样的异步操作在程序运行时不会阻塞代码执行,这意味着如果操作未完成,程序的其他部分也可以运行。

使用fs.rmdir和fs.rmdirSync删除目录

要异步删除目录,我们可以使用rmdir函数。它需要3个参数。

第一个是目录的路径,可以是字符串,Buffer对象或URL对象。

第二个参数是一个带有一些选项属性的对象。 emFileWait属性是一个整数,如果遇到EMFILE错误,则让我们的程序重试。

这是我们等待再次尝试删除目录的最大毫秒数。 rmdir函数将每1ms重试一次,直到达到emFileWait值。

默认值为1000。maxBusyTries是一个整数,是遇到EBUSY,ENOTEMPTY或EPERM错误时的重试次数。它将每100毫秒重试一次,直到maxBusyTries值。递归属性是一个布尔属性。

如果将其设置为true,则它将递归删除目录中的数据以及目录本身。在递归模式下,如果路径不存在并且在失败时重试操作,则不会报告错误。默认值为false。

递归模式是一项实验功能。最后一个参数是具有err参数的回调函数。删除操作结束时调用。如果目录删除操作成功,则为null。

否则,它将返回带有错误信息的对象。将rmdir函数的常规异步版本与文件一起使用会导致Promise被拒绝,在Windows上出现ENOENT错误,在POSIX操作系统上出现ENOTDIR错误。

例如:

const fs = require("fs");

const dirToDelete = "./files/deleteFolder";

fs.rmdir(
dirToDelete,
{
emfileWait: 2000,
maxBusyTries: 5,
recursive: false
},
err => {
if (err) {
throw err;
}
console.log("Removal complete!");
}
);

如果运行了上面的代码,则存在给定路径的目录,如果该目录存在并且未被其他程序使用,则应删除该目录。

rmdir函数的同步版本是rmdirSync函数。 它采用与rmdir函数类似的参数。 第一个参数是目录的路径,可以是字符串,Buffer对象或URL对象。

第二个参数是具有一个选项属性的对象。 递归属性是一个布尔属性。 如果将其设置为true,则它将递归删除目录中的数据以及目录本身。 在递归模式下,如果路径不存在并且在失败时重试操作,则不会报告错误。 默认值为false。

递归模式是一项实验功能。 返回undefined。

我们可以像下面的代码一样使用rmdirSync函数:

const fs = require("fs");

const dirToDelete = "./files/deleteFolder";

fs.rmdirSync(dirToDelete, {
recursive: false
});

console.log("Removal complete!");

如果运行了上面的代码,则存在给定路径的目录,如果该目录存在并且未被其他程序使用,则应删除该目录。

rmdir函数的promise版本与常规rmdir函数具有相同的作用。它需要2个参数。第一个是目录的路径,可以是字符串,Buffer对象或URL对象。第二个参数是一个带有一些选项属性的对象。

emFileWait属性是一个整数,如果遇到EMFILE错误,则让我们的程序重试。这是我们等待再次尝试删除目录的最大毫秒数。 rmdir函数将每1ms重试一次,直到达到emFileWait值。预设值为1000。

maxBusyTries是一个整数,是遇到EBUSY,ENOTEMPTY或EPERM错误时的重试次数。它将每100毫秒重试一次,直到maxBusyTries值。

递归属性是一个布尔属性。如果将其设置为true,则它将递归删除目录中的数据以及目录本身。在递归模式下,如果路径不存在并且在失败时重试操作,则不会报告错误。默认值为false。

递归模式是一项实验功能。它返回一个promise,当目录删除操作成功时,promise将不带任何参数进行解析。将rmdir函数的Promise版本与文件一起使用会导致Promise被拒绝,Windows上出现ENOENT错误,POSIX操作系统上出现ENOTDIR错误。

我们可以像下面的代码一样使用它:

const fsPromises = require("fs").promises;

const dirToDelete = "./files/deleteFolder";

(async () => {
try {
await fsPromises.rmdir(dirToDelete, {
emfileWait: 2000,
maxBusyTries: 5,
recursive: false
});
console.log("Removal complete!");
} catch (error) {
console.error(error);
}
})();

如果运行上面的代码,对于给定的目录路径,如果该目录存在并且未被其他程序使用,则会删除该目录。对于使用async和await语法,我们使用try ... catch块捕获错误。

最后

rmdir系列允许我们通过指定路径来删除目录。 rmdir函数的异步版本(包括常规版本和promise版本)可以指定发生错误时如何重试,处理错误也非常方便和优雅。