我怎样才能dynamic生成一个文件名列表,用于与Grunt任务?

我正在使用load-grunt-config和grunt-prompt ,并且正在开发一个init任务,它在两个文件夹之间复制一些php模板。

现在的模板文件名是硬编码的,但我宁愿有grunt扫描正确的文件夹,并提供dynamic的文件名。

我试过使用grunt.file.expand ,但我无法得到它的工作。 是否有可能扫描一个文件夹,并返回一个数组(或对象,不知道你会怎么称呼它)的文件名格式grunt-prompt所期待的?

// ------------------------------------- // Grunt prompt // ------------------------------------- module.exports = { // ----- Initialization prompt ----- // init: { options: { questions: [{ // Set the authors name config: 'init.author.name', type: 'input', message: 'What is your name?' }, { // Set the name of the project config: 'init.project.name', type: 'input', message: 'What is the name of your project?' }, { // Select templates to be used config: 'init.php.templates', type: 'checkbox', message: 'Which templates do you want to use?', choices: [{ name: '404.php', checked: false }, { name: 'archive.php', checked: false }, { name: 'comments.php', checked: false }] }] } } }; 

顺便说一句,我已经find了这个答案: https : //stackoverflow.com/a/22270703/1694077 ,这涉及到这个问题。 但没有详细说明如何专门解决这个问题。 另外,我需要更具体的语法,而不仅仅是一个文件名数组:

 [{ name: '404.php' }, { name: 'archive.php' }] 

基本原则

这是一个使用Grunt的文件匹配function获取文件列表的方法。 以下代码将在名为templates的子目录中寻找templates 。 你只需要把你的php文件在那里,脚本会find它。 注意我没有使用load-grunt-config因为它不是获取文件列表的具体问题的一个因素。

关键是使用grunt.file.expand获取文件。

 module.exports = function (grunt) { // List all files in the templates directory. var templates = grunt.file.expand({filter: "isFile", cwd: "templates"}, ["*"]); // Make actual choices out of them that grunt-prompt can use. var choices = templates.map(function (t) { return { name: t, checked: false}; }); grunt.initConfig({ prompt: { init: { options: { questions: [{ // Set the authors name config: 'init.author.name', type: 'input', message: 'What is your name?' }, { // Set the name of the project config: 'init.project.name', type: 'input', message: 'What is the name of your project?' }, { // Select templates to be used config: 'init.php.templates', type: 'checkbox', message: 'Which templates do you want to use?', choices: choices }] } } } }); grunt.task.loadNpmTasks("grunt-prompt"); grunt.registerTask("default", ["prompt"]); }; 

你可以使用比"*"更复杂的东西作为模式。 例如,如果你要在那里有其他types的文件,你不想列出"*.php"将被指示。 我也使用isFile filter选项来避免列出目录。 列出文件之前 ,我使用cwd将工作目录更改为templates ,这意味着返回的文件名包含templates/名称。 也可以这样做:

 var templates = grunt.file.expand({filter: "isFile"}, ["templates/*"]); 

并获取包含名称中的templates/目录的文件列表。

使用load-grunt-config

默认情况下, load-grunt-config一个package.json文件(因为它调用了load-grunt-tasks )。 这是我用过的:

 { "dependencies": { "load-grunt-config": "^0.8.0", "grunt-prompt": "^1.1.0", "grunt": "^0.4.4" } } 

Gruntfile.js变成:

 module.exports = function (grunt) { grunt.registerTask("default", ["prompt"]); require('load-grunt-config')(grunt); }; 

然后在grunt/prompt.js你需要这个:

 module.exports = function(grunt) { // List all files in the templates directory. var templates = grunt.file.expand({filter: "isFile", cwd: "templates"}, ["*"]); // Make actual choices out of them that grunt-prompt can use. var choices = templates.map(function (t) { return { name: t, checked: false}; }); return { init: { options: { questions: [{ // Set the authors name config: 'init.author.name', type: 'input', message: 'What is your name?' }, { // Set the name of the project config: 'init.project.name', type: 'input', message: 'What is the name of your project?' }, { // Select templates to be used config: 'init.php.templates', type: 'checkbox', message: 'Which templates do you want to use?', choices: choices }] } } }; }; 

这里是一个简短的代码来列出一个目录中的文件:

 var fs = require("fs") var files = []; var list = function (path) { fs.readdirSync(path).forEach(function (file) { if(fs.lstatSync(path + '/' +file).isDirectory()) list(path + '/' +file); else files.push({name: file}); }); } list(YOUR_PATH) console.log(files) 

在你的例子中:

 var fs = require("fs") var files = []; var list = function (path) { fs.readdirSync(path).forEach(function (file) { if(fs.lstatSync(path + '/' +file).isDirectory()) list(path + '/' +file); else files.push({name: file}); }); } list(YOUR_PATH) module.exports = { // ----- Initialization prompt ----- // init: { options: { questions: [{ // Set the authors name config: 'init.author.name', type: 'input', message: 'What is your name?' }, { // Set the name of the project config: 'init.project.name', type: 'input', message: 'What is the name of your project?' }, { // Select templates to be used config: 'init.php.templates', type: 'checkbox', message: 'Which templates do you want to use?', choices: files }] } } }; 

还有另一种方法可以使用与接受的答案中列出的不同的Grunt实用程序方法。 值得一提的是,它公开了Grunt内部使用的“glob”npm包的选项对象。

有关更多信息(请查看package.json文件),请参阅README.md了解您的Grunt版本使用的glob版本。 我首先查看了最新的glob,并对Grunt没有grunt.file.globSync ()方法的事实感到困惑。 我最终意识到Grunt正在使用glob的早期版本,之后从选项对象中删除了{ synctrue },并由我一直在寻找的globSync ()函数取代。

注意: grunt.file.glob ()不像grunt.file.expand ()那样需要一个src数组,但是你可以使用大括号来有效地对一个数组进行编码:

 var options = { ... }; var results = grunt.file.glob( '{first/path/**/*,second/path/**/*}', options ); 

下面是一个示例块,展示了如何在玉石处理中使用它,我似乎记得,由于某种原因,本身并不处理扩展块。 选项:

  • 允许通配符匹配点前缀的文件
  • 禁用非通配符全局模式path节点的不必要的统计调用
  • 禁用sorting,因为我不关心input顺序
  • 禁用重复删除,因为我知道我的模式只匹配每个文件一次
  • 如果没有文件匹配,则请求一个空数组而不是数组

    var filesObj = {}; var configObj = {build:{options:{pretty:true,data:{titleStr:'This is a title from data'}},files:filesObj}};

    //获取源代码并从configuration文件构build输出目录根var srcPrefix = new RegExp('^'+ grunt.config.get('sourceAssets')); var buildPrefix = grunt.config.get('buildAssets');

    //每次循环匹配调用一次来填充文件对象。 函数addJadeFile(srcPath){//通过denormlalizingpath在Windows上处理glob输出。 srcPath = srcPath.replace(/ \ / g,'/'); //提取公共path后缀并更改文件扩展名var relPath = srcPath.replace(srcPrefix,'..')。replace(/。jade $ /,'.html'); //将目标path前缀和属性//前置到configuration对象的文件子对象。 filesObj [buildPath + relPath] = srcPath; }

    grunt.file.glob(appConfig.source.client +'/**/*.jade',{sync:true,stat:false strict:true,dot:false,nonull:false,nodir:true,nosort:true, noun:true}).forEach(addJadeFile);

    返回configObj;

PS grunt.file.glob ()和grunt.file.expand ()通常优于fs包的遍历方法,因为glob保留了遍历caching。

如果您正在查找可能由以前的构build步骤创build的文件,而不是在其他任务首先遍历其创build位置并填充该caching之前,那么了解glob的遍历caching也是一件好事。 我还没有遇到这个问题,但是要注意,以防万一你需要找出如何在这种情况下清除或忽略caching。