NodeJS - error EPERM when moving file to its parent directory? - node.js

I found this answer saying to use mv module.
But it doesn't seem it works if I want to move file to its parent directory.
For example I want to move all files on /tmp to /
var root = process.cwd(); // the directory where i run the script
mv(root + "/tmp", root, { mkdirp: true }, function(err) {
if(err) { return logger.error(err); }
});
and I got this error:
error: Error: EPERM, rename 'C:\Users\myusername\Documents\test\tmp'
I think it's because moving in NodeJS uses rename workaround and it can't rename it to the parent directory.
Any solution? Thanks

Nevermind, used fs-extra module here.
the fs.move actually works

Related

Node.JS rename file in mounted drive

I want to be able to rename files using Node.JS and then rename them back via a separate system and then rename them again via Node.JS.
When renaming a file using Node.JS fs.rename it works the first time, but when trying renaming it back to the original name and then running Node.JS fs.rename to rename it again it does not work, there's no error or anything. i.e.
await fs.promises.rename('/var/lib/sitecontents/old.csv', '/var/lib/sitecontents/new.csv') # Works
# Rename back to old.csv using Window file browser connected to the share
await fs.promises.rename('/var/lib/sitecontents/old.csv', '/var/lib/sitecontents/new.csv') # Doesn't work, no error
I tried using the fs-extras library and the move function and it returned this error: "Error: Source and destination must not be the same.", even thought the files had different names.
I have also tried to copy and delete
const rename = async (path) => {
const newPath = `${path}_processed`;
try {
await fs.promises.copyFile(path, newPath, async (err) => {
if (err) throw err;
await fs.promises.unlink(path, (ierr) => {
if (ierr) throw ierr;
console.log(`-----removed: ${path}`);
});
console.log(`-----moved: ${path}, ${newPath}`);
});
} catch (t) {
console.log(t);
}
}
Which gives me this message:
UnhandledPromiseRejectionWarning: Error: Unknown system error -116
I have also tried child_process.exec with no luck
exec(`mv ${path} ${newPath}`);
Error I am getting from that is
{
killed: false,
code: 1,
signal: null,
cmd: 'mv /var/lib/sitedata/azure_devops_integration/dev/twoo.csv /var/lib/sitedata/azure_devops_integration/dev/twoo.csv.error',
stdout: '',
stderr: 'mv: ‘/var/lib/sitedata/azure_devops_integration/dev/twoo.csv’ and ‘/var/lib/sitedata/azure_devops_integration/dev/twoo.csv.error’ are the same file\n'
}
I'm using Node.JS 12.19.0 on RHEL. The folder that the files are in is mounted via a shared drive, and there is only issues when renaming the files back to the original name via windows share. If I rename the files using RHEL and the mv command there is no issue.

Error: ENOENT: no such file or directory, unlink

As you can see, there is a file at the path. But fs says no such file or directory. I can't understand why?
In another file, I can remove with the same code.
My boat.js file:
boat.findById(req.params.id,function(err, foundBoat) {
if(err){
console.log(err);
}else{
foundBoat.boatsFoto.forEach(function(path){
console.log(typeof(path));
fs.unlink("../public"+path,function(err){
if(err) throw err;
console.log('File deleted!');
});
});
}
});
And it is my error:
Error: ENOENT: no such file or directory, unlink '../public/uploads/akingokay/BoatsFoto/1524411110335kiralik-tekne.jpg'
at Error (native)
And you can see my file system
Can you try this instead:
fs.unlink("public"+path,function(err){
if(err) throw err;
console.log('File deleted!');
});
You should first install the path module via CLI:
npm install path --save
and use it:
fs.unlink(path.join("public/" + path, photo.id + ".jpg"), function(response) {
// handle the callback
});
Check if the path variable you are adding to the "/public" has a "/" at the beginning. If there is no/ seperating it it will treat the path as one.
Install and import path module. this helps you https://nodejs.org/api/path.html
Instead of "../public"+path use path.join("../", "public", path);
It depends where you host the server. If it is on a local machine then you will probably need to specify the complete path to the file(s) that you want to delete or manipulate. If it is on a web server that is live then you will need to specify the complete path to it.
on a "local machine" it might look something like this:
fs.unlink('/home/user/project/someothername/'+filename, err => {
// handler
});
Consider like you are in app.js file and give the relative path of deleting file to the fs.unlink('path/to/file'). it will work!

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

Renaming file with nodejs

I'm trying to rename a file, and I think I'm going mad my code is simple, I check if the file exists, and if it exists, I rename it. Here is the code :
if (fs.existsSync(__dirname+"/"+req.files.file.path))
{
fs.rename(__dirname+"/"+req.files.file.path, __dirname+"/app/upload/portfolio/video/"+req.files.file.name, function(err) {
if (err)
throw err;
else
....
});
}
But I get this error (I've replaced the realpath by path/to/file) :
throw err;
^
Error: ENOENT, rename 'path/to/file/filename.mp4'
After a check, I see that the file exists (simply by copy/paste the filepath in the error)
What can be the reason of such an issue?
rename can fail with ENOENT not only if the source doesn’t exist, but also if the directory of the destination doesn’t exist. I suspect app/upload/portfolio/video/path/to/file does not exist.

Node.js fs.unlink function causes EPERM error

I'm using fs.unlink() to delete a file and I receive the following error:
uncaught undefined:
Error: EPERM, Operation not permitted '/Path/To/File'
Anyone know a why this is happening?
You cannot delete a directory that is not empty.
And fs.unlinkSync() is used to delete a file not a folder.
To remove an empty folder, use
fs.rmdir()
to delete a non empty folder, use this snippet:
var deleteFolderRecursive = function(path) {
if( fs.existsSync(path) ) {
fs.readdirSync(path).forEach(function(file) {
var curPath = path + "/" + file;
if(fs.lstatSync(curPath).isDirectory()) { // recurse
deleteFolderRecursive(curPath);
} else { // delete file
fs.unlinkSync(curPath);
}
});
fs.rmdirSync(path);
}
};
Snippet from stackoverflow: Is node.js rmdir recursive ? Will it work on non empty directories?
If you want to achieve something like rm -rf does, there is a package from npm called rimraf which makes it very easy.
Maybe the Path of the file is located is erroneus.
if not, try with fs.unlinkSync()
Yes, you don't have permission to delete/unlink that file. Try again with more rights or verify that you're giving it the right path.

Resources