当目标中已存在具有匹配名称的文件夹时,使用nodejs复制文件夹并为其名称添加后缀

Using nodejs to copy a folder and add a suffix to its name when folder with matching name already exists in the destination

我正在调用一个 Feathers JS API 来复制一个包含一些文件的文件夹。假设我的文件夹名称是 'Website1'

Linux 的正常行为是,它将新文件夹名称附加为 'Website1 copy' 并进一步附加为 'Website1 another copy''Website1 3rd copy'等。

可以用ShellJS实现吗?

我的代码:

function after_clone_website(hook) {
  return new Promise((resolve, reject) => {
    let sourceProjectName = hook.params.query.sourceProjectName;
    let destinationProjectName = sourceProjectName + '_copy';

    let userDetailId = hook.params.query.userDetailId;

    let response = '';

    response = shell.cp('-Rf', config.path + userDetailId + '/' + 
        sourceProjectName, config.path + userDetailId + '/' +
        destinationProjectName);

    hook.result = response;
    resolve(hook)

  });
}

ShellJS 不包含模拟 Linux 相同行为的内置逻辑。 IE。这是追加; ...复制,...另一个副本,...第三个副本,...第 4 次复制etc,当目标路径中的文件夹已存在且与正在复制的源文件夹同名时,复制到文件夹名称)。

解决方案:

你可以使用 ShellJS test() method with the -e option to check whether each potential variation of the path exists. If it does exist then run your own custom logic to determine what the correct destination path value in the cp() 方法应该是。

自定义逻辑应该是什么?

以下要点包括一个接受两个参数的自定义 copyDirAndRenameIfExists() 函数;源文件夹的路径和目标文件夹的路径(与 ShellJS cp() 函数的工作方式非常相似)。

var path = require('path'),
    shell = require('shelljs');

/**
 * Copies a given source folder to a given destination folder.
 *
 * To avoid potentially overwriting an exiting destination folder, (i.e. in the
 * scenario whereby a folder already exists in the destination folder with the
 * same name as the source folder), the source folder will be renamed following
 * normal Linux behaviour. I.e. One of the following values will be appended as
 * appropriate: `copy`, `another copy`, `3rd copy`, `4th copy`, etc.
 *
 * @param {String} srcDir - Path to the source directory to copy.
 * @param {String} destDir - Path to the destination directory.
 * @returns {Object} Object returned from invoking the shelljs `cp()` method.
 */
function copyDirAndRenameIfExists(srcDir, destDir) {
    var dirName = path.basename(srcDir),
        newDirName = '',
        hasCopied = false,
        counter = 0,
        response = {};

    /**
     * Helper function suffixes cardinal number with relevent ordinal
     * number suffix. I.e. st, nd, rd, th
     * @param {Number} number - The number to suffix.
     * @returns {String} A number with its ordinal number suffix.
     */
    function addOrdinalSuffix(number) {
        var j = number % 10,
            k = number % 100;

        if (j === 1 && k !== 11) {
            return number + 'st';
        }
        if (j === 2 && k !== 12) {
            return number + 'nd';
        }
        if (j === 3 && k !== 13) {
            return number + 'rd';
        }
        return number + 'th';
    }

    /**
     * Helper function to get the appropriate folder name suffix.
     * @param {Number} num - The current loop counter.
     * @returns {String} The appropriate folder name suffix.
     */
    function getSuffix(number) {
        if (number === 1) {
            return ' copy';
        }
        if (number === 2) {
            return ' another copy';
        }
        return ' ' + addOrdinalSuffix(number) + ' copy';
    }

    /**
     * Helper function copies the source folder recursively to the destination
     * folder if the source directory does not already exist at the destination.
     */
    function copyDir(srcDir, destDir) {
        if (!shell.test('-e', destDir)) {
            response = shell.cp('-R', srcDir, destDir);
            hasCopied = true;
        }
    }

    // Continuously invokes the copyDir() function
    // until the source folder has been copied.
    do {
        if (counter === 0) {
            copyDir(srcDir, path.join(destDir, dirName));
        } else {
            newDirName = dirName + getSuffix(counter);
            copyDir(srcDir, path.join(destDir, newDirName));
        }
        counter += 1;

    } while (!hasCopied);

    return response;
}

实施

  1. 将(上面)提供的要点中的 copyDirAndRenameIfExists() 函数添加到您现有的节点程序中。

  2. 确保在程序开始时 require 节点内置 path 模块(除了 shelljs)(如果你不已经有了)。 IE。添加以下内容:

    var path = require('path');
  1. 最后通过更改问题中提供的代码行调用自定义 copyDirAndRenameIfExists() 函数:

    response = shell.cp('-Rf', config.path + userDetailId + '/' +
        sourceProjectName, config.path + userDetailId + '/' + destinationProjectName);
    

    改为:

    response = copyDirAndRenameIfExists(
      path.join(config.path, userDetailId, sourceProjectName),
      path.join(config.path, userDetailId, destinationProjectName)
    };