Gulp merge json files from different folders while keeping folder structure

℡╲_俬逩灬. 提交于 2020-01-23 18:25:47

问题


I would like to merge multiple .json files from different folders while keeping the general folder structure.

Input

/lang/module1/file1.json
/lang/module1/file2.json
/lang/module2/file1.json
/lang/module2/subModule1/file1.json

/lang_additional/module1/file1.json
/lang_additional/module1/file2.json
/lang_additional/module2/file1.json
/lang_additional/module2/subModule1/file1.json

Expected Output

/dist/lang/module1/file1.json                (both file1.json's merged)
/dist/lang/module1/file2.json                (both file2.json's merged)
/dist/lang/module2/file1.json                (both file1.json's merged)
/dist/lang/module2/subModule1/file1.json     (both file1.json's merged)

Is it possible to achieve this with gulp? There may be multiple folders and subfolders. I wish to designate which parent folder has precedence in the merge conflict resolution.


回答1:


This works for your example input and I believe any number of subfolders in each folder. If there is a matching file in another directory it is added to a streams array that will then be used to start the necessary number of gulp streams to send to 'gulp-merge-json' and your 'dist' output with the folder structure retained.

Use with "gulp mergeJSON"

var gulp = require('gulp');
var fs = require('fs');
var path = require('path');
var merge = require('gulp-merge-json');

const files = [];
const parentFolders = [];
let   streams = [];
const baseNames = [];

//    note that the way 'gulp-merge-json' works is the last file having the same key as an earlier file 'wins' on the merge
//    so whichever directory is listed last in the folders array will have PRECEDENCE
//   'gulp-merge-json' will also take an 'edit' function option

// [  in the comments you said you wanted the 'lang' folder structure preserved in './dist'
//     but with 'lang_additional' precedence  ]

//  By the way, this works with more than two directories or it can work with
// folders of different levels such as:
//         const folders = ['lang', 'lang_additional/module1/subModule2'];
// only merging those files with the same directory structure starting at the deepest
// levels only. So in the above example, only within subModule2 and below.

const folders = ['lang', 'lang_additional'];

gulp.task('mergeJSON', function () {

  getFiles(folders);
  makeStreams();

    // streams[1] =   lang\module1\file2.json,   lang_additional\module1\file2.json

  // spin up multiple "streams", not really a stream yet until gulp.src creates one
  streams.forEach(function (stream) {

    //  get the fileName from one of the stream files, they all end with the same file
    let fileName = path.basename(stream[stream.length - 1]);

    //  get the directories of one of the streams, again all files within a stream have the same directories
    let dirName = path.dirname(stream[stream.length - 1]);
    // strip off the first directory, leaving all subdirectories
    dirName = dirName.substr(dirName.indexOf(path.sep));

    return gulp.src(stream)
      .pipe(merge({ fileName: fileName }))

      // since the question wanted a dist/lang/subfolders hierarchy
      .pipe(gulp.dest(path.join('./dist', 'lang', dirName)));
  });
});

// getFiles is recursive, if a "file" retrieved by fs.readdirSync is a directory

function getFiles(folders) {

  let possibleDirectory;

  folders.forEach(function (folder, index) {

    // read the file list from each directory
    let tempFiles = fs.readdirSync('./' + folder);

    tempFiles.forEach(function (fileOrDirectory) {

      possibleDirectory = path.join(folder, fileOrDirectory);
      if (fs.lstatSync(possibleDirectory).isDirectory())  {
        getFiles([possibleDirectory]);
      }
      else {

        // files[] will include all files found under the folders array
        files.push(path.join(folder, fileOrDirectory));

        if (baseNames.indexOf(fileOrDirectory) === -1) {

          // if that file name element doesn't already exist in baseName array
          // an array of just the basenames of true files
          baseNames.push(fileOrDirectory);
        }
      }
    });
  });
}

function makeStreams() {

  // for each file, find and save its parent directories without the folders[] "root" directories
  files.forEach(function (file) {

    let thisParentFolders = path.dirname(file).substr(file.indexOf(path.sep));

    if (parentFolders.indexOf(thisParentFolders) === -1) {

      // if that parentfolder  doesn't already exist in baseName array
      parentFolders.push(thisParentFolders);
    }
  });

  // now loop through all unique directories looking for those files with each parentFolder with baseName attached
  parentFolders.forEach(function (folder) {

    let foldersFile = folder.substr(folder.indexOf(path.sep));

    baseNames.forEach(function (baseName) {

      streams.push(files.filter(function (file) {
         return file.endsWith(path.join(foldersFile, baseName));
      }));
    });
  });

  //    Here: remove any "streams" (array sub-elements) that have only one file in them, length == 1
  //    But for now this filter is necessary due to a undefined entry in .
  streams = streams.filter( stream => stream.length >= 1);

  streams.forEach( (stream, index) => console.log("streams[" + index + "] = " + stream));
}


来源:https://stackoverflow.com/questions/46605923/gulp-merge-json-files-from-different-folders-while-keeping-folder-structure

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!