DEV Community

Alex Adam
Alex Adam

Posted on • Originally published at alexadam.dev

Convert Files and Folders Structures to Bash Scripts, with NodeJS

This is a simple NodeJS app that takes a source folder as input and generates a Bash script. The Bash script has all the files' content and the folders' structure in the source folder and it can recreate them when executed.

Source code available here: https://github.com/alexadam/folders-to-script

First step, iterate through all files in the source folder:

const fs = require("fs")
const path = require("path")

const listFiles = (dirPath, result) => {
 files = fs.readdirSync(dirPath)

 result = result || ['#!/bin/sh']

 for (const file of files) {
   ///...
 }

 return result
}

const allFiles = listFiles(rootPath)

fs.writeFileSync('./result.sh', allFiles.join('\n'))
Enter fullscreen mode Exit fullscreen mode

If file is a directory, add an mkdir -p command:

for (const file of files) {
 if (fs.statSync(dirPath + "/" + file).isDirectory()) {
 result.push(`mkdir -p ${path.join(dirPath, "/", file).replace(rootPath, '.')}`)
 result = listFiles(dirPath + "/" + file, result)
 } 
}

Else, test if file is binary or text, based on its extension:

const textExt = ['txt', 'md', 'html', 'json', 'js', 'jsx', 'ts', 'tsx'];
const binaryExt = ['jpg', 'png', 'gif', 'pdf', 'mp3', 'mp4'];

const getFileExt = (filePath) => filePath.split('.').pop()

...
    else {
      const filePath = path.join(dirPath, "/", file);
      const fileExt = getFileExt(filePath);
      const fileContent = fs.readFileSync(filePath);

      if (textExt.includes(fileExt)) {
        result.push(`
cat > ${path.join(dirPath, "/", file).replace(rootPath, '.')} << "EOF"
${fileContent}
EOF
`)
      } else if (binaryExt.includes(fileExt)) {
        const bindata = fileContent.toString('binary');
        const hexdata = new Buffer(bindata, 'ascii').toString('hex');
        result.push(`echo '${hexdata}' | xxd -r -p > ${path.join(dirPath, "/", file).replace(rootPath, '.')}`)
      }
    }
...

Binary files are stored as hex strings.

You can add/remove file extensions in the textExt or binaryExt arrays.

This is the full NodeJS script:

const fs = require("fs")
const path = require("path")

const rootPath = process.argv[2]

const textExt = ['txt', 'md', 'html', 'json', 'js', 'jsx', 'ts', 'tsx'];
const binaryExt = ['jpg', 'png', 'gif', 'pdf', 'mp3', 'mp4'];

const getFileExt = (filePath) => filePath.split('.').pop()

const listFiles = (dirPath, result) => {
  files = fs.readdirSync(dirPath)

  result = result || ['#!/bin/sh']

  for (const file of files) {
    if (fs.statSync(dirPath + "/" + file).isDirectory()) {
      result.push(`mkdir -p ${path.join(dirPath, "/", file).replace(rootPath, '.')}`)
      result = listFiles(dirPath + "/" + file, result)
    } else {
      const filePath = path.join(dirPath, "/", file);
      const fileExt = getFileExt(filePath);
      const fileContent = fs.readFileSync(filePath);

      if (textExt.includes(fileExt)) {
        result.push(`
cat > ${path.join(dirPath, "/", file).replace(rootPath, '.')} << "EOF"
${fileContent}
EOF
`)
      } else if (binaryExt.includes(fileExt)) {
        const bindata = fileContent.toString('binary');
        const hexdata = new Buffer(bindata, 'ascii').toString('hex');
        result.push(`echo '${hexdata}' | xxd -r -p > ${path.join(dirPath, "/", file).replace(rootPath, '.')}`)
      }
    }
  }

  return result
}

const allFiles = listFiles(rootPath)

fs.writeFileSync('./result.sh', allFiles.join('\n'))

Test it with node index.js test -> it will generate a Bash script file named result.sh

Then, in an empty directory, execute the script with sh result.sh.

Discussion (0)