How do I interact with this <File> object in a node.js stream?
Asked Answered
R

3

21

I'm using gulp to build a stream of glob-matched files and move them all, in their nested structure, to a new location. To do this, I first wanted to build a simple 'through' stream to see what I get passed if I pipe to it from gulp.src().

Here is my test gulpfile.js:

var through = require("through");
var fs = require("fs");

function write(file) {
  console.log(file);
  console.log(file.toString());
}

gulp.task("move", function () {

  return gulp.src("./**")
    .pipe(through(write));

});

If I run the gulp 'move' task on the command line, I get output like the following:

<File "some/path">
[object Object]
<File "some/path/file.js" <Buffer 2f 2a 0a 0a 4f 72 67 69 6e 61 6c 20 53 74 79 6c 65 20 66 72 6f 6d 20 65 74 68 61 6e 73 63 68 6f 6f 6e 6f 76 65 72 2e 63 6f 6d 2f 73 6f 6c 61 72 69 7a 65 ...>>
[object Object]

What are those objects? How can I interact with them?

Reinareinald answered 9/3, 2014 at 19:21 Comment(0)
J
26

Those are vinyl objects. They are the core data type passed through gulp streams. The contain information about the file (such as path info and contents as a buffer or stream). You can see the data better using gulp-debug.

If you want to move a bunch of files, while preserving their relative path, you can do one of the following, no need to dig into the code yourself:

gulp.src('/a/single/src/path/**/*.foo').pipe(gulp.dest('/a/single/dest/path'));

Or, if you have a bunch of different globs:

gulp.src(['/a/src/path/foo/**/*.foo', '/a/src/path/bar/**/*.bar'], {base: '/a/src/path/'})
    .pipe(gulp.dest('/a/dest/path/'));

Mostly you'll be using gulp plugins to manipulate the files, then passing the result to gulp.dest(), rather than manipulating them yourself.

If you need to manipulate the files, there's a few plugins that can help:

  • gulp-tap allows you to peak into the stream, and optionally modify the file or buffer.
  • vinyl-map lets you easily modify the contents of files
  • gulp-filter can help you filter the stream if globbing doesn't work.
Jessiajessica answered 9/3, 2014 at 19:49 Comment(1)
Thanks, @OverZealous, this is right. And for some reason I just never realized that gulp.src(glob).pipe(gulp.dest(new)) would preserve all of the nested structure, but I got that working earlier today. As a general rule, I prefer not to use plugins until I understand how they work, but this didn't even need a plugin. Thanks for the tip!Reinareinald
B
11

You can view the file properties using this js:

var propValue;
for(var propName in file) {
    propValue = file[propName];
    console.log('name:' + propName, ', value:<<<',propValue,'>>>');
}

Sample Output
    name:history ,     value:"C:\Temp\test.txt"
    name:cwd ,         value:"C:\Temp"
    name:base ,        value:"C:\Temp"
    name:_contents ,   value: full file contents
    name:isBuffer ,    value:"function () {
    name:isStream ,    value:"function () {
    name:isNull ,      value:"function () {
    name:isDirectory , value:"function () {
    name:clone ,       value:"function (opt) {
    name:pipe ,        value:"function (stream, opt) {
    name:inspect ,     value:"function () {
    name:stat , value:<<< { dev: 0,
      mode: 33206,
      nlink: 1,
      uid: 0,
      gid: 0,
      rdev: 0,
      ino: 0,
      size: 874,
      atime: Sat Sep 19 2015 14:34:51 GMT+1000 (AUS Eastern Standard Time),
      mtime: Sat Sep 19 2015 14:34:51 GMT+1000 (AUS Eastern Standard Time),
      ctime: Sat Sep 12 2015 14:59:40 GMT+1000 (AUS Eastern Standard Time) } >>>

Usage:
console.log('file name:', file.relative);
console.log('file current working directory:', file.cwd);
console.log('file isDirectory:', file.isDirectory());
Britteny answered 20/10, 2015 at 19:21 Comment(0)
L
0

For those who also stumbled upon this and don't want to use gulp, here is how I did it:

Assuming files is an array of vinyl objects -

        const outputPath = ... // some directory path

        files.forEach(file => {
            const filePath = path.join(outputPath, file.relative);
            // if its a directory then create the directory if not already present
            if (file.isDirectory()) {
              if (!fs.existsSync(filePath)) {
                fs.mkdirSync(filePath, { recursive: true });
              }
            } else {
              // if its a file then save the contents of the file
              fs.writeFileSync(filePath, file.contents);
            }
          });
Lollipop answered 1/12, 2018 at 22:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.