How can I open an Image file using fs in NodeJS? - javascript

In my current codes, it does only can read a text file, How can I make an Image (base64) file opened with Photos Application (Windows)? Is there any chance to do that? If it's impossible, please let me know!
const fs = require('fs')
fs.readFile('./Test/a.txt', 'utf8' , (err, data) => {
if (err) {
console.error(err)
return
}
console.log(data)
return
})

Another possible solution is like this:
const cp = require('child_process');
const imageFilePath = '/aaa/bbb/ccc'
const c = cp.spawn('a_program_that_opens_images', [ `"${imageFilePath}"` ]);
c.stdout.pipe(process.stdout);
c.stderr.pipe(process.stderr);
c.once('exit', exitCode => {
// child process has exited
});

Do something like this:
const cp = require('child_process');
const c = cp.spawn('bash'); // 1
const imageFilePath = '/aaa/bbb/ccc'
c.stdin.end(`
program_that_opens_images "${imageFilePath}"
`); // 2
c.stdout.pipe(process.stdout); // 3
c.stderr.pipe(process.stderr);
c.once('exit', exitCode => { // 4
// child process has exited
});
what it does:
spawns a bash child process (use sh or zsh instead if you want)
writes to bash stdin, (inputting the command to run)
pipes the stdio from the child to the parent
captures the exit code from the child

Related

Check if child_process can run a command in NodeJS

how can I check if child_process can run a command?
'echo' is a valid command that can be run in a terminal, but 'echoes' is not one. For example, if I do this
const cp = require('child_process')
cp.exec('echo hello')
it will work.
If I do this, though
const cp = require('child_process')
cp.exec('echoes hello') //notice how it is echoes instead of echo
it will just error, but maybe the user has a program that adds 'echoes' to a terminal, and in that case, it would be able to run, but if it errors it will just exit out of the process and I won't be able to check if it works.
Is there any way to do this? Thank you so much in advance!
You have to manually loop through dirs in $PATH env & perform look up on those directory.
eg: $PATH is set to /bin:/usr/local/bin then you have to perform
fs.access('/bin/' + command, fs.constants.X_OK)
and
fs.access('/usr/local/bin/' + command, fs.constants.X_OK)
solution would look like this.
const { constants: fsconsts } = require('fs')
const fs = require('fs/promises')
const path = require('path')
const paths = process.env.PATH.split(':')
async function isExecutable(command) {
const cases = []
for (const p of paths) {
const bin = path.join(p, command)
cases.push(fs.access(bin, fsconsts.X_OK)) // X_OK is bit flag which makes sure file is executable
}
await Promise.any(cases)
return command
}
const found = (bin) => console.log('found', bin)
const notfound = (errors) => {
console.log('not found or not executable')
// console.error(errors)
}
// passes
isExecutable('echo').then(found).catch(notfound)
isExecutable('node').then(found).catch(notfound)
// fails
isExecutable('shhhhhh').then(found).catch(notfound)
isExecutable('echoes').then(found).catch(notfound)
NOTE: I think my solution works only on *nix based OSs

command handler only recognize the top-most folder instead of all the folders

i have a problem, my Command Handler only recognize the top Folder inside my Commands Directory. Its supposed to show all of the available Folder in Commands Directory but it only showed the 'test' category which is the top one. any help would be really appreciated.
Folder/Directory Construction:
console.log output:
Command Handler Code:
const {readdirSync} = require('fs');
const ascii = require('ascii-table');
let table = new ascii("Commands");
table.setHeading('Category', 'Command', ' Load status');
var logged = false;
const path = require('node:path')
module.exports = (client) => {
readdirSync('./Commands/').forEach(dir => {
var commands = readdirSync(`./Commands/${dir}/`).filter(file => file.endsWith('.js'));
for(let file of commands){
let pull = require(`../Commands/${dir}/${file}`);
if(pull.name){
client.commands.set(pull.name, pull);
table.addRow(dir,file,'✔️ -> Command Loaded')
} else {
table.addRow(dir,file,'❌ -> Command Error')
continue;
}
if(pull.aliases && Array.isArray(pull.aliases)) pull.aliases.forEach(alias => client.aliases.set(alias, pull.name))
}
if(!logged) {
console.log(table.toString())
console.log(`[Command] Command Handler is Ready! | Total Commands: ${commands.length}`)
logged = true
}
});
}
I believe you are overwriting the commands variable after each folder has been looped through. Try this:
const {readdirSync} = require('fs');
const ascii = require('ascii-table');
let table = new ascii("Commands");
table.setHeading('Category', 'Command', ' Load status');
var logged = false;
const path = require('node:path')
module.exports = (client) => {
readdirSync('./Commands/').forEach(dir => {
var commands = []
commands.push(readdirSync(`./Commands/${dir}/`).filter(file => file.endsWith('.js')));
for(let file of commands){
let pull = require(`../Commands/${dir}/${file}`);
if(pull.name){
client.commands.set(pull.name, pull);
table.addRow(dir,file,'✔️ -> Command Loaded')
} else {
table.addRow(dir,file,'❌ -> Command Error')
continue;
}
if(pull.aliases && Array.isArray(pull.aliases)) pull.aliases.forEach(alias => client.aliases.set(alias, pull.name))
}
if(!logged) {
console.log(table.toString())
console.log(`[Command] Command Handler is Ready! | Total Commands: ${commands.length}`)
logged = true
}
});
}
If this doesn't help than it might still be that issue I referred to above but the edits I made might not be compatible with your code.

How to use Cspell --file-list stdin

I wanted to use cspell --file-list command as a child process in Node Js.
I wanted to pass large array of strings to this child process and feed it by stdin.
var child = spawn('cspell --file-list',[], {shell:true});
Now I wanted to pass strings one by one to this child process.
Can someone help me in this with small example.
send files as an argument:
const spawn = require('child_process').spawn;
const cmd = 'cspell';
const checkFiles = (files) => {
const proc = spawn(cmd, ['--file-list'].concat(files), {shell: true });
const buffers = [];
proc.stdout.on('data', (chunk) => buffers.push(chunk));
proc.stderr.on('data', (data) => {
console.error(`stderr: ${data.toString()}`);
});
proc.stdout.on('end', () => {
const result = (Buffer.concat(buffers)).toString();
console.log(`done, result:\n${result}`);
});
};
// pass files array
checkFiles(['some-file', 'another-file']);

How can I grab files from inside a parent directory and all subdirectories inside?

I want to grab all javascript files inside the parent directory and in all sub directories for my discord.js command handler. How do I achieve that?
I have a working block of code that already grabs all .js files from the parent directory, but all sub directories are left alone.
const botConfig = require('./config/nvdconfig.json');
const Discord = require('discord.js');
const fs = require('fs');
const prefix = botConfig.prefix;
// nvdColor: #45c263
const bot = new Discord.Client({
disableEveryone: true
});
bot.commands = new Discord.Collection();
const {
readdirSync,
statSync
} = require('fs');
const {
join
} = require('path');
fs.readdir('./cmds/', (err, files) => {
if (err) console.error(err);
let jsfiles = files.filter(f => f.split('.').pop() === 'js');
if (jsfiles.length <= 0) {
return console.log('No commands to load.');
return;
}
console.log(`Loading ${jsfiles.length} commands!`);
jsfiles.forEach((f, i) => {
let props = require(`./cmds/${f}`);
console.log(`${i + 1}: ${f} loaded!`);
bot.commands.set(props.help.name, props);
});
});
I expect the same result from the loading of the jsfiles through the parent directory as well as all current and future subdirectories.
My current result is all js files are being loaded in but the ones inside the subdirectories are left alone.
I would really appreciate if someone could help me with this! Thank you in advance.
So, I figured out how to get the result that I want.
I found a node package called fs-readdir-recursive that had everything I wanted.
Install the package: npm install fs-readdir-recursive --save
And initialize it. const <var name> = require('fs-readdir-recursive');
Then after you do that, create another variable. const <var name> = read('./<parent directory>/');
This variable will be the parent directory that is searched through with a for each loop.
const <var name> = require('fs-readdir-recursive');
const files = read('./cmds/');
files.forEach(file => {
let cmd = file.replace('.js', '');
let props = require(`./cmds/${cmd}`);
<your code here>
});
This will read each file in each directory of the parent.

how to use grep command programmatically in node.js

I am trying to Display only the vmRSS Attribute. When I run the command command
cat ./Status
I get alot of attributes and their corresponding values. What I am trying to do is to Display only the vmRSS programmatically. I can do it in the console as follows:
cat ./status | grep VmR
but how can I do it programmatically.
my attempts
const ls2 = spawn('cat', ['/proc/' + process.pid + '/status']);
Since child_process spawn launch a shell in a subprocess, I think you're better to do that within the current shell instead, with child_process exec() command.
Here is an example (thanks to #Inian):
const { exec } = require('child_process');
exec('grep VmR /proc/' + process.pid + '/status', (err, stdout) => {
if (err) return console.log(err)
console.log(stdout) // VmRSS: 13408 kB
})
Otherwise, if you don't want to spawn a shell to get that info, you could use fs to read the file, something like that:
const fs = require('fs');
let process_status = '/proc/' + process.pid + '/status';
fs.readFile(process_status, { encoding: 'utf8' }, (err, buf) => {
if (err) return console.log(err)
let lines = buf.split('\n') // each line in an array
let line = lines.filter(line => /VmRSS/.test(line)) // find interesting line
let VmR = line[0].replace(/\t/g, '') // clean output removing tabulation
console.log(VmR) // VmRSS: 13208 kB
})

Categories