Can't find the file I created by fs.writeFile - node.js

I am trying to write a file in node.js using fs.writeFile, I use the following code:
const fs = require('filer');
const jsonString = JSON.stringify(myObj)
fs.writeFile('/myFile.txt', jsonString, function (err) {
if (err) throw err;
console.log('Saved!');
});
}
I am sure the file is created, because I can read it by fs.readFile referring to the same address, but I cannot find it on the disk by using windows search. What I understood, if I change the localhost port it saves the files in another location. I already tried "process.cwd()", but it didn't work.
I really appreciate it if someone could help.

try to use : __dirname instead of process.cwd()
const fs = require('fs');
const path = require('path');
const filePath = path.join(__dirname, '/myFile.txt');
console.log(filePath);
const jsonString = JSON.stringify({ name: "kalo" })
fs.writeFile(filePath, jsonString, (err) => {
if (err) throw err;
console.log('The file has been saved!');
});
And I would like to know why are you using 'filer' instead of default fs module?
fs module is native module that provides file handling in node js. so you don't need to install it specifically. This code perfectly worked and it prints absolute location of the file as well.Just run this code if it doesn't work, I think you should re install node js. I have updated the answer.You can also use fs.writeFileSync method as well.

From documentation: "String form paths are interpreted as UTF-8 character sequences identifying the absolute or relative filename. Relative paths will be resolved relative to the current working directory as determined by calling process.cwd()."
So in order to determine your working directory (i.e. where fs create files by default) call (works for me):
console.log(process.cwd());
Then if you would like to change your working directory, you can call (works for me as well):
process.chdir('path_to_new_directory');
Path can be relative or absolute.
This is also from documentation: "The process.chdir() method changes the current working directory of the Node.js process or throws an exception if doing so fails (for instance, if the specified directory does not exist)."

Related

How to read the contents of a file onto the console using Nodejs

I am going back to learning js after many years off and all i want to do is read the contents of a file onto the console using Nodejs. I found the sample code. Nice and simple. I have spent over an hour trying to figure out why it will not find the file. This is sample right off the documentation and i made it exactly like the example to debug it. The absolute only difference is the name joe is replaced with my user folder.
const fs = require('fs')
fs.readFile('/Users/gendi/test.txt', 'utf8' , (err, data) => {
if (err) {
console.error(err)
return
}
console.log(data)
})
It runs fine except it will not find test.text. no matter what. I receive the following error and no matter how i format the file path. Nothing.
C:\Users\gendi>node readfile.js
[Error: ENOENT: no such file or directory, open 'C:\Users\gendi\test.txt'] {
errno: -4058,
code: 'ENOENT',
syscall: 'open',
path: 'C:\\Users\\gendi\\pcsSnipe\\test.txt'
}
You can also only pass in the file path as 'test.txt' and the exact same results come up. on the first part of the error msg the path looks formatted correctly but on the last line of the error msg it is not? Its been years.. so i know i am missing something really simple. I assure that file is there!! Thank you in advance and forgive my ineptness.
The fs module requires an exact path to the file you'd like to read. A simple fix to this would be to add __dirname which will return the directory path along with the path of your file.
// Define modules
const fs = require('fs');
const path = require('path');
// Read the file
fs.readFile(path.join(__dirname, '/Users/gendi/test.txt'), 'utf8' , (err, data) => {
if (err) // If FS returned an error
return console.error(err); // Log the error and return
console.log(data); // If the reading was successful, log the data
});
It works if you remove the file extention, '.txt' . Idk why it make a differnce. maybe the "." is throwing it off but it doesn't matter in this respect. Thank you

reading a packaged file in aws lambda package

I have a very simple node lambda function which reads the contents of packaged file in it. I upload the code as zip file. The directory structure is as follows.
index.js
readme.txt
Then have in my index.js file:
fs.readFile('/var/task/readme.txt', function (err, data) {
if (err) throw err;
});
I keep getting the following error NOENT: no such file or directory, open '/var/task/readme.txt'.
I tried ./readme.txt also.
What am I missing ?
Try this, it works for me:
'use strict'
let fs = require("fs");
let path = require("path");
exports.handler = (event, context, callback) => {
// To debug your problem
console.log(path.resolve("./readme.txt"));
// Solution is to use absolute path using `__dirname`
fs.readFile(__dirname +'/readme.txt', function (err, data) {
if (err) throw err;
});
};
to debug why your code is not working, add below link in your handler
console.log(path.resolve("./readme.txt"));
On AWS Lambda node process might be running from some other folder and it looks for readme.txt file from that folder as you have provided relative path, solution is to use absolute path.
What worked for me was the comment by Vadorrequest to use process.env.LAMBDA_TASK_ROOT. I wrote a function to get a template file in a /templates directory when I'm running it locally on my machine with __dirname or with the process.env.LAMBDA_TASK_ROOT variable when running on Lambda:
function loadTemplateFile(templateName) {
const fileName = `./templates/${templateName}`
let resolved
if (process.env.LAMBDA_TASK_ROOT) {
resolved = path.resolve(process.env.LAMBDA_TASK_ROOT, fileName)
} else {
resolved = path.resolve(__dirname, fileName)
}
console.log(`Loading template at: ${resolved}`)
try {
const data = fs.readFileSync(resolved, 'utf8')
return data
} catch (error) {
const message = `Could not load template at: ${resolved}, error: ${JSON.stringify(error, null, 2)}`
console.error(message)
throw new Error(message)
}
}
This is an oldish question but comes up first when attempting to sort out whats going on with file paths on Lambda.
Additional Steps for Serverless Framework
For anyone using Serverless framework to deploy (which probably uses webpack to build) you will also need to add the following to your webpack config file (just after target: node):
// assume target: 'node', is here
node: {
__dirname: false,
},
Without this piece using __dirname with Serverless will STILL not get you the desired absolute directory path.
I went through this using serverless framework and it really was the file that was not sent in the compression. Just add the following line in serverless.yml:
package:
individually: false
include:
- src/**
const filepath = path.resolve('../../filename.text');
const fileData2 = fs.readFileSync(process.env.LAMBDA_TASK_ROOT + filepath, 'utf-8');
I was using fs.promises.readFile(). Couldn't get it to error out at out. The file was there, and LAMBDA_TASK_ROOT seemed right to me as well. After I changed to fs.readFileSync(), it worked.
I hade the same problem and I tried applying all these wonderful solutions above - which didn't work.
The problem was that I setup one of the folder name with one letter in upper case which was really lowercase.
So when I tried to fetch the content of /src/SOmething/some_file.txt
While the folder was really /src/Something/ - I got this error...
Windows (local environment) is case insensitive while AWS is not!!!....

How to create a directory in the current directory in Node.js

I am new to Node.js, so I'm not familiar with a lot of stuff.
So basically I want to create a directory in the current working directory:
var mkdirp = require('mkdirp');
console.log("Going to create directory /tmp/test");
mkdirp('/tmp/test',function(err){
if (err) {
return console.error(err);
}
console.log("Directory created successfully!");
});
My current directory is C:\Users\Owner\Desktop\Tutorials\NodeJS on Windows, which means I run node main.js in that directory.
(main.js is in C:\Users\Owner\Desktop\Tutorials\NodeJS)
After I run the code, it generates C:\tmp\test, which is in C:\.
But I want to create it in the current directory, so the result I want is C:\Users\Owner\Desktop\Tutorials\NodeJS\tmp\test.
I just don't know how to do that...
You can use process.cwd() to output the directory where your command has been executed (in your case, the directory where you run node main.js) so your code might look like this:
var mkdirp = require('mkdirp');
var path = require('path');
console.log("Going to create directory /tmp/test");
mkdirp(path.join(process.cwd(), '/tmp/test'), function(err){
if (err) {
return console.error(err);
}
console.log("Directory created successfully!");
});
If you need just the directory where the main.js file is located and not where you execute it (by calling node main.js), you can use the __dirname variable instead of process.cwd().
It's a good idea to use the path.join() function to make sure the path delimiters are set correctly, especially when you're on a Windows system which may treat forward slashes as options.
var mkdirp = require('mkdirp');
var path = require('path');
console.log("Going to create directory /tmp/test");
mkdirp(path.join(__dirname, '/tmp/test'),function(err){
if (err) {
return console.error(err);
}
console.log("Directory created successfully!");
});
You could use path.join(__dirname, '/tmp/test') where __dirname would return The name of the directory that the currently executing script resides in.
You need to include module 'path' to make path.join() work.
Reference
__dirname

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).

How do I get the path to the current script with Node.js?

How would I get the path to the script in Node.js?
I know there's process.cwd, but that only refers to the directory where the script was called, not of the script itself. For instance, say I'm in /home/kyle/ and I run the following command:
node /home/kyle/some/dir/file.js
If I call process.cwd(), I get /home/kyle/, not /home/kyle/some/dir/. Is there a way to get that directory?
I found it after looking through the documentation again. What I was looking for were the __filename and __dirname module-level variables.
__filename is the file name of the current module. This is the resolved absolute path of the current module file. (ex:/home/kyle/some/dir/file.js)
__dirname is the directory name of the current module. (ex:/home/kyle/some/dir)
So basically you can do this:
fs.readFile(path.resolve(__dirname, 'settings.json'), 'UTF-8', callback);
Use resolve() instead of concatenating with '/' or '\' else you will run into cross-platform issues.
Note: __dirname is the local path of the module or included script. If you are writing a plugin which needs to know the path of the main script it is:
require.main.filename
or, to just get the folder name:
require('path').dirname(require.main.filename)
Use __dirname!!
__dirname
The directory name of the current module. This the same as the path.dirname() of the __filename.
Example: running node example.js from /Users/mjr
console.log(__dirname);
// Prints: /Users/mjr
console.log(path.dirname(__filename));
// Prints: /Users/mjr
https://nodejs.org/api/modules.html#modules_dirname
For ESModules you would want to use:
import.meta.url
This command returns the current directory:
var currentPath = process.cwd();
For example, to use the path to read the file:
var fs = require('fs');
fs.readFile(process.cwd() + "\\text.txt", function(err, data)
{
if(err)
console.log(err)
else
console.log(data.toString());
});
Node.js 10 supports ECMAScript modules, where __dirname and __filename are no longer available.
Then to get the path to the current ES module one has to use:
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
And for the directory containing the current module:
import { dirname } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));
When it comes to the main script it's as simple as:
process.argv[1]
From the Node.js documentation:
process.argv
An array containing the command line arguments. The first element will be 'node', the second element will be the path to the JavaScript file. The next elements will be any additional command line arguments.
If you need to know the path of a module file then use __filename.
var settings =
JSON.parse(
require('fs').readFileSync(
require('path').resolve(
__dirname,
'settings.json'),
'utf8'));
Every Node.js program has some global variables in its environment, which represents some information about your process and one of it is __dirname.
I know this is pretty old, and the original question I was responding to is marked as duplicate and directed here, but I ran into an issue trying to get jasmine-reporters to work and didn't like the idea that I had to downgrade in order for it to work. I found out that jasmine-reporters wasn't resolving the savePath correctly and was actually putting the reports folder output in jasmine-reporters directory instead of the root directory of where I ran gulp. In order to make this work correctly I ended up using process.env.INIT_CWD to get the initial Current Working Directory which should be the directory where you ran gulp. Hope this helps someone.
var reporters = require('jasmine-reporters');
var junitReporter = new reporters.JUnitXmlReporter({
savePath: process.env.INIT_CWD + '/report/e2e/',
consolidateAll: true,
captureStdout: true
});
Use the basename method of the path module:
var path = require('path');
var filename = path.basename(__filename);
console.log(filename);
Here is the documentation the above example is taken from.
As Dan pointed out, Node is working on ECMAScript modules with the "--experimental-modules" flag. Node 12 still supports __dirname and __filename as above.
If you are using the --experimental-modules flag, there is an alternative approach.
The alternative is to get the path to the current ES module:
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(new URL(import.meta.url));
And for the directory containing the current module:
import { fileURLToPath } from 'url';
import path from 'path';
const __dirname = path.dirname(fileURLToPath(new URL(import.meta.url)));
You can use process.env.PWD to get the current app folder path.
NodeJS exposes a global variable called __dirname.
__dirname returns the full path of the folder where the JavaScript file resides.
So, as an example, for Windows, if we create a script file with the following line:
console.log(__dirname);
And run that script using:
node ./innerFolder1/innerFolder2/innerFolder3/index.js
The output will be:
C:\Users...<project-directory>\innerFolder1\innerFolder2\innerFolder3
If you are using pkg to package your app, you'll find useful this expression:
appDirectory = require('path').dirname(process.pkg ? process.execPath : (require.main ? require.main.filename : process.argv[0]));
process.pkg tells if the app has been packaged by pkg.
process.execPath holds the full path of the executable, which is /usr/bin/node or similar for direct invocations of scripts (node test.js), or the packaged app.
require.main.filename holds the full path of the main script, but it's empty when Node runs in interactive mode.
__dirname holds the full path of the current script, so I'm not using it (although it may be what OP asks; then better use appDirectory = process.pkg ? require('path').dirname(process.execPath) : (__dirname || require('path').dirname(process.argv[0])); noting that in interactive mode __dirname is empty.
For interactive mode, use either process.argv[0] to get the path to the Node executable or process.cwd() to get the current directory.
index.js within any folder containing modules to export
const entries = {};
for (const aFile of require('fs').readdirSync(__dirname, { withFileTypes: true }).filter(ent => ent.isFile() && ent.name !== 'index.js')) {
const [ name, suffix ] = aFile.name.split('.');
entries[name] = require(`./${aFile.name}`);
}
module.exports = entries;
This will find all files in the root of the current directory, require and export every file present with the same export name as the filename stem.
If you want something more like $0 in a shell script, try this:
var path = require('path');
var command = getCurrentScriptPath();
console.log(`Usage: ${command} <foo> <bar>`);
function getCurrentScriptPath () {
// Relative path from current working directory to the location of this script
var pathToScript = path.relative(process.cwd(), __filename);
// Check if current working dir is the same as the script
if (process.cwd() === __dirname) {
// E.g. "./foobar.js"
return '.' + path.sep + pathToScript;
} else {
// E.g. "foo/bar/baz.js"
return pathToScript;
}
}

Resources