Is there a way to list the file extension of all files in a directory node.js? - node.js

So when I use fs.readdir() I only get the file name and if I use .split(".") it wont work since if I have a folder called a.exe it will say that .exe is the extension even that it's not since folders don't have a extension.
Here is the code for fs.readdir()
fs.readdir("./", (err,data)=>{
if (err) throw err
console.log(data)
})
Console: (a.exe is a folder and aa.exe is a file)
[ 'a.exe', 'aa.exe' ]
Any way to get the file extension or get whether its a folder or file (that will help too)
https://i.stack.imgur.com/yE0oD.png

I used to 'file-system' module.
This is tutorial that use this module.
fs.recurse('path', function(filepath, relative, filename) { });
fs.recurse('path', [
'*.css',
'**/*.js',
'path/*.html',
'!**/path/*.js'
], function(filepath, relative, filename) {
if (filename) {
// it's file
} else {
// it's folder
}
});
// Only using files
fs.recurse('path', function(filepath, relative, filename) {
if (!filename) return;
});
You can find more info in here

Related

Bulk Renaming Files Based on JSON in Node Recurisvely

I'm wanting to bulk rename files within a folder based on a JSON file that I have with the following format:
{
"1": {
"Filename": "Background-1",
"New Filename": "Background-1#4"
},
"2": {
"Filename": "Background-2",
"New Filename": "Background-2#6"
},
The original Filenames are within a folder structure such as
Background
--Background-1
--Background-2
Other Folder
--Another-Filename
--Another-Filename-2
And so on and so forth. I want to copy the files with the new names, while retaining the name of the folder they're in, over to a new folder.
So far I've tried using fs and klaw-sync to read the filenames, traverse through directories, etc, but it seems wildly inefficient to run through each key and then run through each folder recurisvely to find a matching file, then rename it and copy. There's over 180 files and ~15 folders.
Any idea how I can approach this better, or any suggestions/examples I could use?
Here's what I've got so far.
Thanks.
// Require Node's File System module
const fs = require('fs');
var path = require('path');
var klawSync = require('klaw-sync');
// Read the JSON file
fs.readFile(__dirname + '/rename_config.json', function (error, data) {
if (error) {
console.log(error);
return;
}
const obj = JSON.parse(data);
// Iterate over the object
Object.keys(obj).forEach(key => {
// Create an empty variable to be accesible in the closure
var paths;
// The directory that you want to explore
var directoryToExplore = path.join(__dirname, '../art');
try {
paths = klawSync(directoryToExplore);
} catch (err) {
console.error(err);
}
//console.log(paths);
//traverse through paths to find an equal name
//find the path of that equivalent name, then rename to new directory
});
});

fs.writeFile not working when the file path has a folder with timestamp

I am trying to write a data to a file which is inside the folder with folder name having timestamp.
fs.writeFileSync(`.files/${process.env.TIMESTAMP}/data.txt`, "Welcome",
"utf8", function (err) {
if (err) {
return console.log(err);
}
});
and as time stamp i mentioned as
`${new Date().toLocaleDateString()}_${new Date().toLocaleTimeString()}`;
There is no error displayed, but its not getting written. If i remove and give as below : its works
fs.writeFileSync('.files/data.txt', "Welcome",
"utf8", function (err) {
if (err) {
return console.log(err);
}
});
Please help me to understand how to give with timestamp.
In first case , the reason is that you are trying to write in to a folder which is not present at all.There is no folder inside files with name ${process.env.TIMESTAMP}.
First create a directory with name as required by you and then try writing into a file in that folder
Do something like this
var dir = `.files/${process.env.TIMESTAMP}`;
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
}
fs.writeFileSync(`.files/` + dir + `/data.txt`, "Welcome",
"utf8", function (err) {
if (err) {
return console.log(err);
}
});
You have couple errors in your code:
1) writeFileSync(file, data[, options]) doesn't have callback as third argument. Callback argument exists only for async version of this method writeFile(file, data[, options], callback).
In this case you should get exception if there will be error:
fs.writeFileSync(`.files/${process.env.TIMESTAMP}/data.txt`, "Welcome", "utf8");
2) This expression could produce not valid folder name:
`${new Date().toLocaleDateString()}_${new Date().toLocaleTimeString()}`
In my browser it produced:
"6/25/2019_2:01:44 PM"
But here is rules for folder and files names in UNIX systems which says:
In short, filenames may contain any character except / (root directory), which is reserved as the separator between files and directories in a pathname. You cannot use the null character.
You should make more safe directory name. Use this approach:
`${d.getFullYear()}_${d.getMonth()}_${d.getDate()}__${d.getHours()}_${d.getMinutes()}`
_ - is allowed character for folders and files names.
3) You need create directory using mkdirSync() before creating files in it

How to add a line at a specific line row to a file's content using node.js and Promises

Situation: I made some code that loops through a main directory and its subdirectories looking for htm files, once it finds the .htm file it is supposed to add a line after the head tag, then it should loop further looking for all other .htm files in the main directory and perfmoring the same action.
The code:
var fs = require("fs");
var path = require("path");
var mainDirectory = 'directory';
function addLineInFile() { //execute the steps needed to alter the file's content in sequential order.
readContent() //can be found below.
.then(lookForHead) //can be found below.
.then(writeNewContent) //can be found below.
}
addLineInFile();
function readContent() {
return new Promise((resolve, reject) => {
FileContent = [];
fs.readFile(extendedDirectoryPath, (err, data) => {
fileContent = data.toString('utf8').split("\n");
console.log("Read file content")
});
if (err) {
reject(err);
} else {
resolve(FileContent);
}
});
}
function lookForHead(FileContent) {
return new Promise((resolve, reject) => {
var string = "<head>"
for (i = 0; i < FileContent.length; i++) {
console.log("Looking for <head>.")
if (FileContent[i].indexOf(string) !== -1) {
console.log("found <head>")
FileContent.splice(i + 1, 0, 'line to be added')
}
}
if (err) {
reject(err);
} else {
resolve(FileContent);
}
});
}
function writeNewContent(FileContent) {
return new Promise((resolve, reject) => {
console.log("Started Writing to the file!")
var file = fs.createWriteStream(extendedDirectoryPath);
file.on('error', function(err) { /* error handling */ });
FileContent.forEach(function(v) {
file.write(v.join(', ') + '\n');
console.log("Wrote a line to the file.")
});
file.end();
if (err) {
reject(err);
} else {
resolve(FileContent);
}
});
}
Problem: The file is written to BEFORE the content that has to be written to it is ready (Take a look at the output). So the writeNewContent() is executed before the readContent() and lookForHead() are done with giving it its content to be written in the file. I've tried so many different things before this like callback functions and was convinced Promises would be my solution but perhaps I'm using them incorrectly? Please keep in mind that I don't know all that much about node.js and Promises most of my work is just copy pasting from internet and changing small parts of it to my liking.
Output:
Got file info successfully!
file1.htm This is an htm file!
Started Writing to the file!
Got file info successfully!
file2.htm This is an htm file!
Started Writing to the file!
Got file info successfully!
file3.htm This is an htm file!
Started Writing to the file!
Got file info successfully!
file4.htm This is an htm file!
Started Writing to the file!
Got file info successfully!
someInnerDirectory is a innerDirectory
Delving deeper!
Got file info successfully!
file5.htm This is anhtm file!
Started Writing to the file!
Got file info successfully!
file6.htm This is an htm file!
Started Writing to the file!
Got file info successfully!
file7.htm This is an htm file!
Started Writing to the file!
Read file content
Read file content
Read file content
Read file content
Read file content
Read file content
Read file content
Well done on your work so far and sticking with it. Good to see you are using recursion too. You are creating a function called addLineInFile but not executing it. I did something similar a while back, check it out

check the type of files is present or not using nodejs

I want to find the type of files which is present or not, I am using nodejs, fs. Here is my code
var location = '**/*.js';
log(fs.statSync(location).isFile());
which always returns the error.
Error: ENOENT, no such file or directory '**/*.js'
How to I find the files is present or not. Thanks in Advance.
node doesn't have support for globbing (**/*.js) built-in. You'll need to either recursively walk the directories and iterate over the array of file names to find the file types you want, or use something like node-glob.
Using recusrive-readdir-sync
var recursiveReadSync = require('recursive-readdir-sync'),
files;
files = recursiveReadSync('./');
files.forEach(function (fileName) {
if (fileName.search(/\.js$/g) !== -1) {
console.log("Found a *.js file");
}
});
Using node-glob:
var glob = require("glob")
glob("**/*.js", function (er, files) {
files.forEach(function (fileName) {
if (fileName.search(/\.js$/g) !== -1) {
console.log("Found a *.js file");
}
});
node.js dose not support "glob" wildcards by default. You can use external package like this one

writeFile no such file or directory

I have a file(data.file an image), I would like to save this image. Now an image with the same name could exist before it. I would like to overwrite if so or create it if it does not exist since before. I read that the flag "w" should do this.
Code:
fs.writeFile('/avatar/myFile.png', data.file, {
flag: "w"
}, function(err) {
if (err) {
return console.log(err);
}
console.log("The file was saved!");
});
Error:
[Error: ENOENT: no such file or directory, open '/avatar/myFile.png']
errno: -2,
code: 'ENOENT',
syscall: 'open',
path: '/avatar/myFile.png'
This is probably because you are trying to write to root of file system instead of your app directory '/avatar/myFile.png' -> __dirname + '/avatar/myFile.png' should do the trick, also check if folder exists. node.js won't create parent folder for you.
Many of us are getting this error because parent path does not exist. E.g. you have /tmp directory available but there is no folder "foo" and you are writing to /tmp/foo/bar.txt.
To solve this, you can use mkdirp - adapted from How to write file if parent folder doesn't exist?
Option A) Using Callbacks
const mkdirp = require('mkdirp');
const fs = require('fs');
const getDirName = require('path').dirname;
function writeFile(path, contents, cb) {
mkdirp(getDirName(path), function (err) {
if (err) return cb(err);
fs.writeFile(path, contents, cb);
});
}
Option B) Using Async/Await
Or if you have an environment where you can use async/await:
const mkdirp = require('mkdirp');
const fs = require('fs');
const writeFile = async (path, content) => {
await mkdirp(path);
fs.writeFileSync(path, content);
}
I solved a similar problem where I was trying to create a file with a name that contained characters that are not allowed. Watch out for that as well because it gives the same error message.
I ran into this error when creating some nested folders asynchronously right before creating the files. The destination folders wouldn't always be created before promises to write the files started. I solved this by using mkdirSync instead of 'mkdir' in order to create the folders synchronously.
try {
fs.mkdirSync(DestinationFolder, { recursive: true } );
} catch (e) {
console.log('Cannot create folder ', e);
}
fs.writeFile(path.join(DestinationFolder, fileName), 'File Content Here', (err) => {
if (err) throw err;
});
Actually, the error message for the file names that are not allowed in Linux/ Unix system comes up with the same error which is extremely confusing. Please check the file name if it has any of the reserved characters. These are the reserved /, >, <, |, :, & characters for Linux / Unix system. For a good read follow this link.
It tells you that the avatar folder does not exist.
Before writing a file into this folder, you need to check that a directory called "avatar" exists and if it doesn't, create it:
if (!fs.existsSync('/avatar')) {
fs.mkdirSync('/avatar', { recursive: true});
}
you can use './' as a prefix for your path.
in your example, you will write:
fs.writeFile('./avatar/myFile.png', data.file, (err) => {
if (err) {
return console.log(err);
}
console.log("The file was saved!");
});
I had this error because I tried to run:
fs.writeFile(file)
fs.unlink(file)
...lots of code... probably not async issue...
fs.writeFile(file)
in the same script. The exception occurred on the second writeFile call. Removing the first two calls solved the problem.
In my case, I use async fs.mkdir() and then, without waiting for this task to complete, I tried to create a file fs.writeFile()...
As SergeS mentioned, using / attempts to write in your system root folder, but instead of using __dirname, which points to the path of the file where writeFile is invoked, you can use process.cwd() to point to the project's directory. Example:
writeFile(`${process.cwd()}/pictures/myFile.png`, data, (err) => {...});
If you want to avoid string concatenations/interpolations, you may also use path.join(process.cwd(), 'pictures', 'myFile.png') (more details, including directory creation, in this digitalocean article).

Resources