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'))
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
.
Also published on https://alexadam.dev/blog/folder-structure-script.html.