Batch with Node.js
Tags: node, javascript, batch, fs
Published: 2021-04-27 13:08:56

---
title: Batch with Node.js
published: true
description: We're going to create a node script to recursively copy/paste mp3 file from nested folders to a root one.
tags: node,js,batch,fs
cover_image: https://coralogix.com/wp-content/uploads/2018/04/Coralogix-Nodejs-integration.jpg
---

## Premise
Let's say that your aunt comes to you asking a favor.

She has this pen drive with A LOT of folders containing mp3s and by what she believes her car cannot read recursively all the folders so she needs one root folder containing all the mp3s.

The USB drive is structured as below:
```
songs |
      folder_1 |
               foo.mp3
               another-foo.mp3
      folder_2 |
               bar.mp3
               another-bar.mp3
...

```
And we need to reach this result:
```
output |
       foo.mp3
       another-foo.mp3
       bar.mp3
       another-bar.mp3
...
```
Given this overview, you have two option to do this:
- Do it manually.
- Leave a like ❤️ to this post.

To start we're gonna create a folder, let's call it `batch-node`.
Inside that folder I've copied the songs folder (above) and I've created an index.js file.
So this is now my **batch-node** structure:
```
batch-node |
           index.js
           songs/
...
```

For this purpose we'll use [fs-extra](https://www.npmjs.com/package/fs-extra) since copy/paste seems like not supported by [fs API](https://nodejs.org/api/fs.html).

Just add it:
```bash
yarn add fs-extra
```

## Let's starting coding.
```javascript
// index.js

/**
 * fs-extra adds file system methods that aren't included in the native
 * fs module and adds promise support to the fs methods.
 */
const fs = require("fs-extra");

const MP3_DIRECTORY = './songs'
const OUTPUT = './output'
```
**Be carefull, do not create output/ folder** since fs-extra will handle this for us otherwise it won't work. 

The script is composed by 2 main functions:
- a `readDirectory` to, of course, read a folder and its content.
- and a `copyToDestination` function to copy our song to the folder destination.

Let's add these functions to our index.js:
```javascript
const copyToDestination = ({ path, file }) => {
    try {
        const fileFormat = path.split('.').pop()
        const isMP3 = fileFormat === 'mp3'
        if (!isMP3) return

        // @see https://stackoverflow.com/a/40019824
        fs.copySync(path, `${OUTPUT}/${file}`)
        console.log(`${ file } has been copied to ${ OUTPUT }`)
    } catch(error) {
        console.error({ error })
    }
}

const readDirectory = dir_name => {
    fs.readdir(dir_name,
        { withFileTypes: false },
        (error, files) => {
            try {
                files.forEach(file => {
                    const path = `${dir_name}/${file}`
                    // @see https://nodejs.org/docs/latest/api/fs.html#fs_stats_isdirectory
                    const isDir = fs.lstatSync(path).isDirectory()
                    const config = { file, path }

                    return isDir ? readDirectory(path) : copyToDestination(config)
                })
            } catch (error) {
                console.error({ error });
            }
        }
    )
}

```
Pay attention to these lines:
```javascript
     const fileFormat = path.split('.').pop()
     const isMP3 = fileFormat === 'mp3'
     if (!isMP3) return
```
Since we have different types of files inside folders (like covers album, ini files and many more) we're returning the function to totally ignore these kinds of file.

Finally we just have to lunch our function at the end of our index.js:
```javascript
readDirectory(MP3_DIRECTORY)
```
![Some logs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gjx5u44ohzs4cy3mhnzs.gif)

This should avoid you some boring manual stuff 🙃