NodeJS fs.rename always thrown an error - node.js

I don't understand one thing with fs.rename(), why this code always throw an error?
The file is correctly renamed but each time i got this error Error: ENOENT: no such file or directory, rename '/path/to/file/example.log' -> '/path/to/file/example_1.log'
var fs = require('fs');
var mv = fs.rename('example.log', 'example_1.log', function(err) {
if(err instanceof Error)
throw err;
});

When I run your exact code:
var fs = require('fs');
var mv = fs.rename('example.log', 'example_1.log', function(err) {
if(err instanceof Error)
throw err;
});
(the only difference is adding the fs require).
Then I get the error when I don't have the file in the current directory.
But when I create example.log and run the program then I don't get any error and the file is renamed.
Of course next time I get the error again because I no longer have the file with the original name.
Are you sure that it doesn't work for you?
By the way, instead of
if (err instanceof Error)
you may want to use:
if (err)
Just in case that your error is not the instance of Error but still is defined (this can be true while using some modules).

Related

Unhandled 'error' event when extracting zip file with nodejs

I want to download a zip file and extract it with nodejs. This is what I have done so far:
var fs = require('fs');
var wget = require('wget-improved');
var filesizeHumanReadable = require('filesize');
var unzip = require('unzip');
var downloadCSS = function() {
var src = 'http://7-zip.org/a/7za920.zip';
var output = '/tmp/7z.zip';
var options = {};
var download = wget.download(src, output, options);
download.on('error', function(err) {
console.log(err);
});
download.on('start', function(fileSize) {
console.log(filesizeHumanReadable(fileSize));
});
download.on('end', function(outputMessage) {
console.log(outputMessage);
console.log(output);
fs.createReadStream(output).pipe(unzip.Extract({ path: '/tmp/' }));
});
download.on('progress', function(progress) {
// code to show progress bar
});
}
The error message I get when running it:
mles-MacBook-Pro:test-api mles$ node index.js
375.83 KB
Finished writing to disk
/tmp/7z.zip
events.js:85
throw er; // Unhandled 'error' event
^
Error: EPERM, unlink '/tmp'
at Error (native)
Now I'm a bit baffled how to handle the error event and what my actual error is?
Does the process have enough permission to write to /tmp? Does /tmp already have some files?
Because unlink is a node.js function to delete directories. Apparently, unzip.Extract calls it. So, unlink fails if the folder isn't empty (in your case /tmp).
Setting the unzip location to a specific directory fixes it
fs.createReadStream(output).pipe(unzip.Extract({ path: '/tmp/7zip' }));
I'm marking mostruash answer as correct since he brought me on the right track.

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

node.js path.rename() throws error despite working correctly

I am renaming files and are getting some weird behavior. It both works and throws an error.
This is the code:
var fs = require('fs');
var file = {
rename: function(from, to){
fs.rename(from, to, function (err) {
if (err) throw err;
console.log("[i] Renamed " + from + " to " + to);
});
}
}
When using it I get this console output:
main.js:1153 [i] Renamed E:\images\oldName.jpg to E:\images\newName.jpg
main.js:1152 Uncaught Error: ENOENT: no such file or directory, rename 'E:\images\oldName.jpg' -> 'E:\images\newName.jpg'
main.js:1152 (anonymous function)
fs.js:73 (anonymous function)
I don't understand what the problem is. The file is renamed anyway.
Also, it doesn't happen if the file is moved to another folder.
Why is this happening and do I have to worry about it?
The function is being called twice. That means the second time it's called the file is no longer there, leading to the 'no such file or directory'. I notice you're using windows which might also be part of the issue. Are you by any chance using fs.watch to call this function? You might be seeing an inherit problem in fs.watch under Windows duplicating events. If so, there's some example code that might help you.

NodeJS Reading all files in a dir by each line

I am fairly new to NodeJS, I am trying to read all files in a given dir and then print out the results line by line using the code below
var fs=require('fs'),fsf = require('fs'),lazy = require('lazy');
var fr;
var dir = '/path/to/dir';
fs.readdir(dir,function(err,files){
if (err) throw err;
files.forEach(function(file){
console.log(file);
fr = fsf.createReadStream(file);
//console.log(fr);
new lazy(fr).lines.forEach(function(line){
console.log(line.toString());
});
});
I am getting the following error
Cannot call method 'toString' of undefined
Any pointers will be really appreciated!
Update: - There were actually two issues
(main) The blank lines in the individual files were causing this
exception.
The hidden files were getting picked up by the program.
Corrected both and here is the refactored code
var fs=require('fs'),lazy = require('lazy');
var fr;
var dir = '/path/to/dir';
fs.readdir(dir,function(err,files){ //Get a listing of all the files in the dir
if (err) throw err;
files.forEach(function(file){
if(file.search('\\.md') != -1) { //Only read markdown files
console.log(file);
fr = fs.createReadStream(file);
new lazy(fr).lines.forEach(function(line){
if (typeof line != 'undefined'){ // Skip blank lines within the files
if ((line.toString().search('\\+') != -1)||(line.toString().search('#') != -1)){
console.log(line.toString());
}
}
});
}
});
});
The code seems fine and is working with other directories and on other machines. After some investigation it seems to be an issue with the .DS_Store hidden files in the directory. I was trying this on a Mac with OSX 10.9.4. I am not 100% sure, but for now that seems to be the likely cause of the error.
Thanks!

NodeJs Method Chaining of fs.mkdir and fs.rename

I'm working on a file uploader script which creates a new folder (based on the timestamp) and moves the uploaded file to the created folder.
Sometimes it works and sometimes I'm getting a ENOENT rename Error (file/folder not exist).
The following code is in my post route:
var form = new multiparty.Form({
uploadDir: "C:"+ path.sep + "files"
});
form.parse(req, function(err, fields, files) {
var dirPath = "C:"+ path.sep + "files" + path.sep + +new Date;
fs.mkdir(dirPath, 0777, function(err, dirPath){
if (err) console.error(err);
console.log("Created new folder");
fs.rename(files.file[i].path, dirPath + path.sep + files.file[i].originalFilename, function(err){
if (err) console.error(err);
console.log("Moved file");
});
}(err, dirPath));
next();
});
I'm using express(4) and the multiparty module.
As you can see I'm using async functions.
So the question is: What is wrong with my code?
Edit
The error I'm talking about: "Error: ENOENT, rename 'C:\files\7384-1r41cry.png'"
It has something to do with a race condition. With fs.mkdirSync everything works fine.
My guess would be some sort of race condition happening here.
This kind of stuff is easy to get wrong and hard to get it right.
I normally use gulp for this kind of stuff and maybe should you :)
To copy a whole directory tree into some other directory wouldn't be easier.
gulp.src('./inputDir/**/*').pipe(gulp.dest('./outputDir')
And all files from inputDir would be copied into outputDir
But maybe coping is not a option. The files could too large, right?
Lets hack it a bit to make it work the way we want.
var fs = require('fs')
, gulp = require('gulp')
, thr = require('through2').obj
, SRC = './test/**/*.{css,html,js}' // it could be 'my/file/located/here'
, OUT = './output' // it could be 'my/newer/file/located/there'
;
gulp.src(SRC)
.pipe(thr(function(chunk, enc, next){
chunk.contents = new Buffer('') // cleaning the contents of the file
chunk._originalPath = chunk.path
next(null, chunk)
}))
.pipe(gulp.dest(OUT))
.pipe(thr(function(chunk, enc, next){
// now a place holder file exists at our destination.
// so we can write to it and being convident it exists
console.log('moving file from', chunk._originalPath, 'to', chunk.path)
fs.rename(chunk._originalPath, chunk.path, function(err){
if (err) return next(err)
next()
})
}))
This moves all css, html and js files from input to output, regardless of how many nested directories there are
gulp is awesome :)
Ok a few things...
you really should start using promises, it makes the code easier to read and the error handling is way superior. I usually use when.js, but there are other alternatives.
you should throw the errors or return on errors or you would try to continue running the function even when the previous operations failed.
you do
if (err) console.error(err);
should be
if (err) throw err;

Resources