Setting path of fs.appendFileSync? - node.js

How do you set the path of fs.appendFileSync? For example, I want to make a file in folder "X" but my code is in the folder above. How would I create the file in another folder than the one my code is in(the file is made in the same folder as the source code).
I've read the documentation but I don't understand how I would be able to specify where to create the file.

The variable __dirname represents the directory that the currently running script is located in. So, if you wanted to put a file in a sub-directory below that (let's say it is in a variable called someDir), then you would do that like this:
const path = require('path');
let pathToFile = path.join(__dirname, someDir, "filename.txt");
fs.appendFileSync(pathToFile, dataToWrite);
If that directory doesn't yet exist and you need to create it, then you could use fs.mkDirSync() to create i.
const path = require('path');
// make sure sub-directory is created
let dirForFile = path.join(__dirname, someDir);
if (!fs.existsSync(dirForFile) {
fs.mkDirSync(dirForFile);
}
// append data to the file
let pathToFile = path.join(dirForFile, "filename.txt");
fs.appendFileSync(pathToFile, dataToWrite);

Related

JSON file not found

I have a json file with the name of email_templates.json placed in the same folder as my js file bootstrap.js. when I try to read the file I get an error.
no such file or directory, open './email_templates.json'
bootstrap.js
"use strict";
const fs = require('fs');
module.exports = async () => {
const { config } = JSON.parse(fs.readFileSync('./email_templates.json'));
console.log(config);
};
email_templates.json
[
{
"name":"vla",
"subject":"test template",
"path": ""
}
]
I am using VS code , for some reason VS code doesnt autocomplete the path as well which is confusing for me.Does anyone know why it is doing this?
Node v:14*
A possible solution is to get the full path (right from C:\, for example, if you are on Windows).
To do this, you first need to import path in your code.
const path = require("path");
Next, we need to join the directory in which the JavaScript file is in and the JSON filename. To do this, we will use the code below.
const jsonPath = path.resolve(__dirname, "email_templates.json");
The resolve() function basically mixes the two paths together to make one complete, valid path.
Finally, you can use this path to pass into readFileSync().
fs.readFileSync(jsonPath);
This should help with finding the path, if the issue was that it didn't like the relative path. The absolute path may help it find the file.
In conclusion, this solution should help with finding the path.

Get filepath/name of a File Descriptor in node.js

How do you get fullpath from a file descriptor in node?
var fs = require('fs')
var fd = fs.openSync('package.json', 'r')
console.log(fd) // 10
console.log(get_file_path_from_fd(fd)) // HELP
Edit: I have found this
> fs.openSync('.', 'r')
10
> fs.readlinkSync('/proc/self/fd/10')
'/home/alfred/repos/test
but i didn't find proc folder in Mac
Considering that you're loading a file that is in the same directory as the script, you could just use the __dirname global to find the current directory.
https://nodejs.org/docs/latest/api/globals.html#globals_dirname
In fact, I prefer to load files using __dirname as part of the path for the fs module as a good practice. For example, this is from a Discord bot I have...
var tokenJSON = require( __dirname + '/json/discord_token.json');
Edit: So to put this into the answer itself; your fd variable contains the data that was loaded from the file, but it is completely disconnected from the file it came from originally. If you are being given an arbitrary file to load and you would like to have the path, we need to know more about how that file is being provided to you. When the file is given to you there should be a path included (so the script can locate the data!) and that is what you want. If there is no path like in your example, then that means the relative paths are the same and it's the current directory.
const {execSync} = require('child_process')
const fs = require('fs')
var fd = fs.openSync('package.json', 'r')
var fullpath = execSync(`lsof -a -p ${process.pid} -d ${fd}`).toString().split('\n')[1].split(/\s+/).pop()
console.log(fullpath) // result: /fullpath/package.json

Dealing with Relative Paths with node.js

I'm wanting to include a .db database file for use with sqlite3 in my node.js project. My problem arises when the module which opens the database connection is required by files in different directories.
My project structure is like so:
project/
|--lib/
| |--foo.js
| `--bar.js
|--db/
| `--database.db
`--server.js
My foo.js file contains opens the database like so:
var sqlite3 = require('sqlite3');
var db = new sqlite3.Database('db/database.db');
module.exports = {
foo: function() {
db.serialize(function() { /* Do database things */ });
}
};
This all works fine when foo.js is required from the server.js file like so:
var foo = require('./lib/foo');
But it doesn't work when required from the file inside the lib directory, bar.js.
var foo = require('./foo');
I assume this is because when this file is initiated from the lib directory then the .db file should actually be ../db/database.db.
How can I get around this, what should I do?
the concept current directory differs when using sqlite3.Database function in different scripts. it works as designed in this line of sqlite3 source code.
So you should explicitly specify the current directory every time you use it. According to your project layout, the correct path to database file in lib/foo.js is
var path = require('path')
// specify current directory explicitly
var db = new sqlite3.Database(path.join(__dirname, '..', 'db', 'database.db'));
Then it works no matter where it requires foo.js.

NodeJS - Copy and Rename all contents in existing directory recursively

I have a directory with folders and files within. I want to copy the entire directory with all its contents to a different location while renaming all the files to something more meaningful. I want to use nodejs to complete this series of operations. What is an easy way to do it, other than moving it one by one and renaming it one by one?
Thanks.
-- Thanks for the comment! So here is an example directory that I have in mind:
-MyFridge
- MyFood.txt
- MyApple.txt
- MyOrange.txt
- ...
- MyDrinks
- MySoda
- MyDietCoke.txt
- MyMilk.txt
- ...
- MyDesserts
- MyIce
...
I want to replace "My" with "Tom," for instance, and I also would like to rename "My" to Tom in all the text files. I am able to copy the directory to a different location using node-fs-extra, but I am having a hard time with renaming the file names.
Define your own tools
const fs = require('fs');
const path = require('path');
function renameFilesRecursive(dir, from, to) {
fs.readdirSync(dir).forEach(it => {
const itsPath = path.resolve(dir, it);
const itsStat = fs.statSync(itsPath);
if (itsPath.search(from) > -1) {
fs.renameSync(itsPath, itsPath.replace(from, to))
}
if (itsStat.isDirectory()) {
renameFilesRecursive(itsPath.replace(from, to), from, to)
}
})
}
Usage
const dir = path.resolve(__dirname, 'src/app');
renameFilesRecursive(dir, /^My/, 'Tom');
renameFilesRecursive(dir, /\.txt$/, '.class');
fs-jetpack has a pretty nice API to deal with problems like that...
const jetpack = require("fs-jetpack");
// Create two fs-jetpack contexts that point
// to source and destination directories.
const src = jetpack.cwd("path/to/source/folder");
const dst = jetpack.cwd("path/to/destination");
// List all files (recursively) in the source directory.
src.find().forEach(path => {
const content = src.read(path, "buffer");
// Transform the path however you need...
const transformedPath = path.replace("My", "Tom");
// Write the file content under new name in the destination directory.
dst.write(transformedPath, content);
});

Get file name from absolute path in Nodejs?

How can I get the file name from an absolute path in Nodejs?
e.g. "foo.txt" from "/var/www/foo.txt"
I know it works with a string operation, like fullpath.replace(/.+\//, ''),
but I want to know is there an explicit way, like file.getName() in Java?
Use the basename method of the path module:
path.basename('/foo/bar/baz/asdf/quux.html')
// returns
'quux.html'
Here is the documentation the above example is taken from.
To get the file name portion of the file name, the basename method is used:
var path = require("path");
var fileName = "C:\\Python27\\ArcGIS10.2\\python.exe";
var file = path.basename(fileName);
console.log(file); // 'python.exe'
If you want the file name without the extension, you can pass the extension variable (containing the extension name) to the basename method telling Node to return only the name without the extension:
var path = require("path");
var fileName = "C:\\Python27\\ArcGIS10.2\\python.exe";
var extension = path.extname(fileName);
var file = path.basename(fileName,extension);
console.log(file); // 'python'
var path = require("path");
var filepath = "C:\\Python27\\ArcGIS10.2\\python.exe";
var name = path.parse(filepath).name;
console.log(name); //python
var base = path.parse(filepath).base;
console.log(base); //python.exe
var ext = path.parse(filepath).ext;
console.log(ext); //.exe
For those interested in removing extension from filename, you can use
https://nodejs.org/api/path.html#path_path_basename_path_ext
path.basename('/foo/bar/baz/asdf/quux.html', '.html');
If you already know that the path separator is / (i.e. you are writing for a specific platform/environment), as implied by the example in your question, you could keep it simple and split the string by separator:
'/foo/bar/baz/asdf/quux.html'.split('/').pop()
That would be faster (and cleaner imo) than replacing by regular expression.
Again: Only do this if you're writing for a specific environment, otherwise use the path module, as paths are surprisingly complex. Windows, for instance, supports / in many cases but not for e.g. the \\?\? style prefixes used for shared network folders and the like. On Windows the above method is doomed to fail, sooner or later.
path is a nodeJS module meaning you don't have to install any package for using its properties.
import path from 'path'
const dir_name = path.basename('/Users/Project_naptha/demo_path.js')
console.log(dir_name)
// returns
demo_path.js
In NodeJS, __filename.split(/\|//).pop() returns just the file name from the absolute file path on any OS platform.
Why need to care about remembering/importing an API while this regex approach also letting us recollect our regex skills.
So Nodejs comes with the default global variable called '__fileName' that holds the current file being executed
My advice is to pass the __fileName to a service from any file , so that the retrieval of the fileName is made dynamic
Below, I make use of the fileName string and then split it based on the path.sep. Note path.sep avoids issues with posix file seperators and windows file seperators (issues with '/' and '\'). It is much cleaner. Getting the substring and getting only the last seperated name and subtracting it with the actulal length by 3 speaks for itself.
You can write a service like this (Note this is in typescript , but you can very well write it in js )
export class AppLoggingConstants {
constructor(){
}
// Here make sure the fileName param is actually '__fileName'
getDefaultMedata(fileName: string, methodName: string) {
const appName = APP_NAME;
const actualFileName = fileName.substring(fileName.lastIndexOf(path.sep)+1, fileName.length - 3);
//const actualFileName = fileName;
return appName+ ' -- '+actualFileName;
}
}
export const AppLoggingConstantsInstance = new AppLoggingConstants();

Resources