头图

I have nothing to do, write some small things in the mentality of learning nodejs, and use the api of nodejs to implement rm, cp and mv to simply delete/copy/move files/folders.

rm delete files

In fact, it is also very simple. If it is a file, delete it directly with fs.unlinkSync. If it is a folder, delete it recursively one by one.

const fs = require("fs");
const { join } = require("path");

module.exports = async function deleteFiles(path) {
  // 判断一下路径是否真实存在
  if (!fs.existsSync(path)) {
    console.warn(new Error("路径不存在。"));
    return;
  }

  const file = fs.lstatSync(path);

  // 是文件,直接删除
  if (file.isFile()) {
    fs.unlinkSync(path);
    return;
  }

  // 是文件夹,遍历下面的所有文件
  if (file.isDirectory()) {
    const files = await fs.readdirSync(path);
    if (files && files.length) {
      for (const fileName of files) {
        // 因为我之前项目使用的时候不想删除隐藏文件,所以在此过滤了.开头的文件
        if (fileName.startsWith(".")) {
          continue;
        }
        const p = join(path, fileName);
        const f = fs.lstatSync(p);
        // 是文件,直接删除
        if (f.isFile()) {
          fs.unlinkSync(p);
        }
        // 是文件夹,递归调用 deleteFiles
        if (f.isDirectory()) {
          await deleteFiles(p);
          // 文件夹内部文件删除完成之后,删除文件夹
          fs.rmdirSync(p);
        }
      }
    }
    return;
  }
};Ï

cp copy file

Copying files is a little bit more than deleting and copying. It is necessary to determine whether oldPath is a file or a folder, and newPath is a file or a folder, and then generate an available path for different situations.

const fs = require("fs");
const { join, dirname, basename } = require("path");

module.exports = async function copyFiles(oldPath, newPath) {
  // 判断路径是否存在,有一个不存在则抛出错误
  if (!fs.existsSync(oldPath) || !fs.existsSync(newPath)) {
    console.warn(new Error("路径不存在。"));
    return;
  }
  const oldFile = fs.lstatSync(oldPath);
  const newFile = fs.lstatSync(newPath);

  // 如果 oldPath 是文件,则直接复制 oldPath
  if (oldFile.isFile()) {
    // 需要考虑 newPath 是文件还是目录
    // 如果是文件路径,则可以直接使用进行复制
    // 如果是目录路径,则需要拼接上 oldPath 的文件名
    if (newFile.isDirectory()) {
      newPath = join(newPath, basename(oldPath));
    }
    fs.copyFileSync(oldPath, newPath);
    return;
  }

  // 如果 oldPath 是目录,则 newPath 应该也使目录
  // 若 newPath 目标路径是文件,则默认复制到文件的目录下
  if (newFile.isFile()) {
    console.warn(new Error("参数2应为路径。"));
    newPath = dirname(newPath);
  }

  if (oldFile.isDirectory()) {
    const files = await fs.readdirSync(oldPath);
    if (files && files.length) {
      // 遍历目录下的所有文件,并将 fileName 拼接上目录路径
      files.forEach(async (fileName) => {
        const oPath = join(oldPath, fileName);
        const oFile = fs.lstatSync(oPath);
        // 如果拼接后的路径为文件,则直接复制
        if (oFile.isFile()) {
          // 当然,新文件也需要拼接上 fileName
          const newFile = join(newPath, fileName);
          fs.copyFileSync(oPath, newFile);
        }
        // 如果是目录,则递归调用 moveFiles
        if (oFile.isDirectory()) {
          const oldDir = join(oldPath, fileName);
          const newDir = join(newPath, fileName);
          // 需要判断拼接后的 newDir 是否存在此目录,如果不存在则创建
          if (!fs.existsSync(newDir)) {
            await fs.mkdirSync(newDir);
          }
          moveFiles(oldDir, newDir);
        }
      });
    }
    return;
  }
};

mv move file

Move files can be lazy, first call the copyFiles function to copy the file, and then call deleteFiles to delete the file is moved hahahaha.

const copyFiles = require("./copy");
const deleteFiles  = require("./delete");

module.exports = async function moveFiles(oldPath, newPath) {
  copyFiles(oldPath, newPath).then((res) => {
    deleteFiles(oldPath);
  });
};

Invoke with the yarn command

Of course, in order to be more realistic, you can configure rm/mv/cp in package.json, which is more like.

"scripts": {
  "rm": "node ./rm.js",
  "mv": "node ./mv.js",
  "cp": "node ./cp.js"
}

It is definitely not possible to configure this directly. We also need to read the input of the command, and use the process that comes with node to read the parameters passed by the command.

// cp.js
const copyFiles = require("./copy");
copyFiles(process.argv[2], process.argv[3]);

// mv.js
const moveFiles = require("./move");
moveFiles(process.argv[2], process.argv[3]);

// rm.js
const deleteFiles= require('./delete')
deleteFiles(process.argv[2])

Finally, you can use it in the form of yarn rm/cp/mv xxx xxx .

# 删除文件
yarn rm ./a.js
# 删除目录
yarn rm ./a

# 移动单个文件
yarn mv ./a.js ./b.js
# 第二个参数为目录时自动取a.js文件名
yarn mv ./a.js ./b
# 移动目录所有文件
yarn mv ./a ./b

# 复制文件
yarn cp ./a/a.js ./b/b.js
# 第二个参数为目录时自动取a.js文件名
yarn cp ./a/a.js ./b
# 复制目录所有文件
yarn cp ./a ./b

shellingfordly
87 声望14 粉丝

普通前端程序员