Javascript,nodejs: give a "string not found" messege on console.log - javascript

The code listed below searches for files that
contains a specified string under it's directory/subdirectories.
to activate it, you type node [jsfilename] [folder] [filename] [ext]
i would also like it to announce: Nothing found in a console.log every time that
a word wasn't found.
ive tried
if (!regex.test(fileContent)) {
console.log(`Noting found`);
it works only if you have one file without your word, but if not ,it loops.
for example if you have 4 files and one of them has the string it wil show
Your word was found in directory: [file]
Noting found
Noting found
Noting found.
So, how can i stop the loop after one !found console.log and how can i prevent it from showing in case of something has found?
const path = require('path');
const fs = require('fs');
function searchFilesInDirectory(dir, filter, ext) {
if (!fs.existsSync(dir)) {
console.log(`Specified directory: ${dir} does not exist`);
return;
}
const files = fs.readdirSync(dir);
const found = getFilesInDirectory(dir, ext);
found.forEach(file => {
const fileContent = fs.readFileSync(file);
const regex = new RegExp('\\b' + filter + '\\b');
if (regex.test(fileContent)) {
console.log(`Your word was found in directory: ${file}`);
}
});
}
function getFilesInDirectory(dir, ext) {
if (!fs.existsSync(dir)) {
console.log(`Specified directory: ${dir} does not exist`);
return;
}
let files = [];
fs.readdirSync(dir).forEach(file => {
const filePath = path.join(dir, file);
const stat = fs.lstatSync(filePath);
if (stat.isDirectory()) {
const nestedFiles = getFilesInDirectory(filePath, ext);
files = files.concat(nestedFiles);
} else {
if (path.extname(file) === ext) {
files.push(filePath);
}
}
});
return files;
}
searchFilesInDirectory(process.argv[2], process.argv[3], process.argv[4]);

Change:
if (!regex.test(fileContent)) {
console.log(`Noting found`);
// ...
to:
if (!printed && !regex.test(fileContent)) {
console.log(`Noting found`);
printed = true;
// ...
and make sure that you have a variable called printed defined in outer scope, originally falsy.

Related

How do I export this named function through module.exports?

I have a command file for a discord bot that contains the command and a piece of parsing logic contained within a function that I want to reuse within my index.js
// file: ./commands/scrumPrompt.js
// The function
const extractDeets = function (f, scrum) {
let items = [];
let re = new RegExp("(\n[ -]*" + f + ".*)", "g");
let replace = new RegExp("[ -]*" + f + "[ ]+");
for (const item of scrum.matchAll(re)) {
items.push(item[1].trim().replace(replace, ""));
}
return items;
};
// The actual command itself within the same file
module.exports = {
name: "scrum",
usage: `!scrum < followed by your message > as per Standup format - refer !show for showing the format`,
description: "Reply to standup prompt",
async execute(message, args) {
if (message.channel.type === "text") {
if (!args.length)
return message.reply(
"Please Provide your scrum as per the format in help menu !scrum < your message >"
);
else {
if (message.author.id !== -1) {
const client = new MongoClient(MONGO_URI);
try {
const database = client.db(DB_NAME);
const members = database.collection("members");
const query = { user_id: message.author.id };
const membersdetail = await members.findOne(query);
if (membersdetail !== null) {
// since this method returns the matched document, not a cursor, print it directly
//console.log("Adding Scrum for ", membersdetail.email);
let userscrum = args.splice(0).join(" ");
// Check if multiple !scrum commands are present in developer scrum message
if (userscrum.includes("!scrum") == false) {
// Expects notations of "-" to exist
let [f, e, b, o, bl] = ["f", "e", "b", "o", "x"];
let features = extractDeets(f, userscrum);
let enhancements = extractDeets(e, userscrum);
let bugs = extractDeets(b, userscrum);
let others = extractDeets(o, userscrum);
let blockers = extractDeets(bl, userscrum);
.
.
.
};
I want to keep the name of the function as extractDeets() itself so that it doesn't mess with the usage within the command as well. I'm not completely sure how to export it into the index.js because it's already kind of being imported here:
// Imports the command file + adds the command to the bot commands collection
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
bot.commands.set(command.name, command);
}
I'm unsure of how to add the function as another import, maybe I should export it into another file and then import it from there? I'm not sure if that's possible or doable here. I've tried directly importing from here but then the command doesn't work, which is troublesome.
You can do it like this:
module.exports = { extractDeets };
Later, you can import it like this:
const { extractDeets } = require('../your_file');

Find first file with given filename

Hello I am trying to find first file with given filename ( piece of filename ).
It works fine but it take a while to take result
There is code
const fs = require("fs");
const dirCheckIn =
"\\\\192.168.2.4\\Photos";
exports.checkUploadedFiles = (req, res) => {
let fileName = req.params.filename;
const getAllFiles = function (dirPath, arrayOfFiles) {
files = fs.readdirSync(dirPath);
arrayOfFiles = arrayOfFiles || [];
files.forEach(function (file) {
if (fs.statSync(dirPath + "/" + file).isDirectory()) {
arrayOfFiles = getAllFiles(dirPath + "/" + file, arrayOfFiles);
} else {
arrayOfFiles.push(file);
}
});
return arrayOfFiles;
};
const uploadedFiles = getAllFiles(inventDirCheckIn);
console.log(uploadedFiles)
let result = uploadedFiles.find(
(result) => result.startsWith(fileName));
if (!result) {
res.send('nothing found')
} else if (result) {
res.send(result)
}
}
It works fine but for example if I have over 7000 photos it takes about 5 sec to get result.
Maybe there is smarter solution?
How can I make it in better way? I want to check if file is uploaded into dir Photos.
I got simple api route /api/getUploadedFiles/:filename
Also I want use startsWith because sometimes I do not know full name of file
/**
*
* #param filePath path to file which is to be checked if it exists.
*/
private checkFileExistsSync(filePath: string) {
let flag = true;
try {
fs.accessSync(filePath, fs.constants.F_OK);
} catch (e) {
flag = false;
}
return flag;
}
// Example usage
// path to the file
const dirCheckIn =
"\\\\192.168.2.4\\Photos";
if (checkFileExistsSync(dirCheckIn)) {
// if the file exists do something...
}
if (!checkFileExistsSync(dirCheckIn)) {
// if the file doesn't exists do something...
}

Return value from async / await try..catch

I have a test folder with files
file
file (1)
file (2)
If the file exists I add a suffix to a new filename, to prevent overwriting the file. For example
if file exists new name should be file (1)
if file (1) exists new name should be file (2)
if file (2) exists new name should be file (3)
and so on.
The following function works fine, except the value is not returned so I can assign it later.
async function dest_exists_new_name(file) {
const access = fs.promises.access
try {
await access(file, fs.F_OK)
// file exists - generate new name
const info = path.parse(file)
const dir = info.dir
let name = info.name
const ext = info.ext
// generate suffix
let suffix = ' (1)'
const suffix_regex = / \([0-9]+\)$/
if (suffix_regex.test(name)) { // if suffix exists -> increment it
const num = name.split(' ').reverse()[0].replace(/[()]/g,'')
const next_num = parseInt(num) + 1
suffix = ' (' + next_num + ')'
name = name.replace(suffix_regex, '') // remove old suffix
}
// generate suffix end
const new_name = path.join(dir, name + suffix + ext)
// recurse until dest not exists
await dest_exists_new_name(new_name)
} catch {
// file not exist - return its name
// console.log works OK
console.log('new name ->', file)
// return doesn't work - returns undefined if the previous name exists, but works ok if the name doesn't exists
return file
}
}
await dest_exists_new_name('/path/file')
new name -> /path/file (3) // console.log - works OK
undefined // returns undefined, if file previously exists
The question is how can I correctly return the new file name value?
If there are any culprits in such a solution like
accidental file rewriting
infinite recursion
other issues
I will be grateful for the hints on how to improve the function.
Your function will return file, but being an async function, you need to await its return and you cannot do so outside of an async scope. Thus, if you just console.log() its "istantaneous" value, it will indeed return a pending promise, as the return value has not been resolved yet. You may retrieve the correct return value by including your function in an async scope, like this:
let a = async () => {
console.log(await dest_exists_new_name('/path/file'))
}
a();
This will output:
new name -> /path/file
/path/file //here's your file
Now, by adding return await dest_exists_new_name(new_name) you should be able to achive what you want and both console.log() and return the new, non-existent, file name. Here's a complete, reproducible example:
const fs = require('fs');
const path = require('path');
async function dest_exists_new_name(file) {
const access = fs.promises.access
try {
await access(file, fs.F_OK)
const info = path.parse(file)
const dir = info.dir
let name = info.name
const ext = info.ext
let suffix = ' (1)'
const suffix_regex = / \([0-9]+\)$/
if (suffix_regex.test(name)) {
const num = name.split(' ').reverse()[0].replace(/[()]/g, '')
const next_num = parseInt(num) + 1
suffix = ' (' + next_num + ')'
name = name.replace(suffix_regex, '')
}
const new_name = path.join(dir, name + suffix + ext)
return await dest_exists_new_name(new_name)
} catch {
console.log('new name ->', file)
return file
}
}
//Here, make sure that the path to "file" is correct
let a = async() => console.log(await dest_exists_new_name(path.join(__dirname, './file')));
a();
Output, having up to file (2) in the same folder:
new name -> /path/to/file (3)
/path/to/file (3)
Check you try catch and how you are receiving your variable.
async function dest_exists_new_name(file) {
try {
const res = await dest_exists_new_name(file1); // recursion result
} catch (err) {
return Promise.resolve("file not found");
}
}
// usage
let res = await dest_exists_new_name(fileArg);
First of all, you should use await, since it's async function:
// recurse until dest not exists
await dest_exists_new_name(new_name)
About recursion - IMHO, it's always better to use cycle (if it doesn't make code too complicated).
Mixing async-await & promises is not very good. Ideally you should use one style.
I prefer to use destructuring, lambda functions, and other modern features.
So, my variant for async-await, without recursion:
const fs = require('fs');
const path = require('path');
// better to create outside of func, since it doesn't depend on context
const suffix_regex = / \([0-9]+\)$/
const defaultSuffix = ' (1)'
const access = async (...params) => new Promise((resolve) => fs.access(...params, (err) => (err) ? resolve(false) : resolve(true)))
const generate_new_suffix = ({ dir, name, ext }) => {
if (suffix_regex.test(name)) { // if suffix exists -> increment it
const num = name.split(' ').reverse()[0].replace(/[()]/g, '')
const suffix = `(${+num + 1})`;
const cleanName = name.replace(suffix_regex, '') // remove old suffix
return path.join(dir, cleanName + suffix + ext)
}
return path.join(dir, name + defaultSuffix + ext)
}
const dest_exists_new_name = async (file) => {
let newNameGenerated = false
let newFileName = file
while (await access(newFileName, fs.F_OK)) {
console.log(newFileName);
const info = path.parse(newFileName)
newFileName = generate_new_suffix(info)
};
console.log('new name ->', newFileName)
return newFileName
}
(async () => {
console.log(await dest_exists_new_name(path.join(__dirname, 'file')))
})();

Node.js: Exported function "is not a function" in one js file, but not another

So one of my files has a function that I need two of my other files to access. I am exporting this function with module.exports = {}. For some reason, one of my files is able to call this function, while I get a commands.commandRouter is not a function error when trying to call it from the other file. Here's basically what I've got going on:
commands.js
function commandRouter(commandName, commandType) {
if (commandType == 'sound') {
console.log(`${commandName} is a sound command, executing sound function`)
playAudio.playAudio(commandName.substring(1));
}
}
module.exports = {commandRouter}
main.js
const commands = require('./modules/commands.js');
const secondary = require('./modules/secondary.js');
client.on('message', (channel, tags, message, self) => {
if(message.charAt(0) == '!'){
console.log('Trigger character identified');
if(commands.commandList.hasOwnProperty(message.toLowerCase())) {
console.log('Valid command identified')
if (commands.commandList[`${message}`] == 'random' ) {
console.log('Random-type command identified')
secondary.randomSelectPropery(message.toLowerCase().substring(1));
}
else
{
console.log('Regular command identified')
commands.commandRouter(message, commands.commandList[`${message}`]);
}
}
}
}
commands.commandRouter(paramA, paramB); works just fine in this instance
secondary.js
const commands = require('./commands.js');
var randomSelectPropery = function (commandObject) {
randomObject = eval(commandObject);
var keys = Object.keys(randomObject);
console.log(randomObject)
console.log(`This object has ${keys.length} commands to choose from`);
var newCommandName = Object.getOwnPropertyNames(randomObject)[keys.length * Math.random() << 0];
console.log(newCommandName)
var newCommandType = randomObject[`${newCommandName}`]
console.log(newCommandType);
commands.commandRouter(newCommandName, newCommandType);
};
const perfect = {
"!perfectqube": "sound",
"!perfectsf2": "sound",
};
module.exports = { perfect, randomSelectPropery }
Here, commands.commandRouter(paramA, paramB); give the commands.commandRouter is not a function error.
File structure is as follows:
.\folder\main.js
.\folder\modules\commands.js
.\folder\modules\secondary.js

Change the way my nodejs app activates

The code listed below searches for files that contains a specified string under it's directory/subdirectories.
to activate it, you type node [jsfilename] [folder] [ext] [term]
i would like to change it so it will search without the base folder, i don't want to type ./ , just node [jsfilename] [ext] [term]
so it already know to search from it's location.
i know it has something to do with the process.argv but it need a hint what should i do.
PS:.
I already tried to change the last raw to :
searchFilesInDirectory(__dirname, process.argv[3], process.argv[2]);
it giving me noting...
const path = require('path');
const fs = require('fs');
function searchFilesInDirectory(dir, filter, ext) {
if (!fs.existsSync(dir)) {
console.log(`Welcome! to start, type node search [location] [ext] [word]`);
console.log(`For example: node search ./ .txt myterm`);
return;
}
const files = fs.readdirSync(dir);
const found = getFilesInDirectory(dir, ext);
let printed = false
found.forEach(file => {
const fileContent = fs.readFileSync(file);
const regex = new RegExp('\\b' + filter + '\\b');
if (regex.test(fileContent)) {
console.log(`Your word has found in file: ${file}`);
}
if (!printed && !regex.test(fileContent)) {
console.log(`Sorry, Noting found`);
printed = true;
}
});
}
function getFilesInDirectory(dir, ext) {
if (!fs.existsSync(dir)) {
console.log(`Specified directory: ${dir} does not exist`);
return;
}
let files = [];
fs.readdirSync(dir).forEach(file => {
const filePath = path.join(dir, file);
const stat = fs.lstatSync(filePath);
if (stat.isDirectory()) {
const nestedFiles = getFilesInDirectory(filePath, ext);
files = files.concat(nestedFiles);
} else {
if (path.extname(file) === ext) {
files.push(filePath);
}
}
});
return files;
}
searchFilesInDirectory(process.argv[2], process.argv[4], process.argv[3]);
If I get what are you trying to achieve. You can do so by slightly changing your function call in the last line.
Change
searchFilesInDirectory(process.argv[2], process.argv[4], process.argv[3]);
to
searchFilesInDirectory(process.cwd(), process.argv[3], process.argv[2]);
Edit
As #Keith said in comments use process.cwd() to get the current working directory instead of __dirname
If you want it to work for both conditions then you need to do a conditional check...
if(process.argv.length === 5){
searchFilesInDirectory(process.argv[2], process.argv[4], process.argv[3]);
}else if(process.argv.length === 4){
searchFilesInDirectory(process.cwd(), process.argv[3], process.argv[2]);
}else{
throw new Error("Not enough arguments provided..");
}

Categories

Resources