How to check whether a directory exists in node.js? - node.js

I'd like to save files received from json object in a REST API app and here is the code:
router.post('/addphoto', checkAuth, (req, res)=> {
let filename = Math.floor(Math.random() * 100000);
let dir = './uploads/' + req.user.id;
//Not sure about this
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
}
base64String = req.body.file;
let base64Image = base64String.split(';base64,').pop();
let filePath = dir + "/" + filename
fs.writeFile( filePath, base64Image, {encoding: 'base64'}, function(err) {
console.log('File created');
});
...
It does the job but I've read that existsSync is deprecated, and also I'm not sure if it's a good idea to use sync code inside a router which is async by nature.
So I'm wondering what is the idiomatic way to do so in such circumstances?

You can use access
fs.access(myDir, function(err) {
if (err && err.code === 'ENOENT') {
fs.mkdir(myDir); //Create dir in case not found
}
});

I've read that existsSync is deprecated
It isn't. See the manual:
fs.exists() is deprecated, but fs.existsSync() is not. The callback parameter to fs.exists() accepts parameters that are inconsistent with other Node.js callbacks. fs.existsSync() does not use a callback.
I'm not sure if it's a good idea to use sync code inside a router which is async by nature.
There's nothing intrinsically wrong about doing something synchronous inside something that is asynchronous — most JS is synchronous — but it does mean that the feature would block the event loop while looking at the file system, and looking at the file system is a relatively time-consuming operation, so it wouldn't be good for performance.
Your code might not need that level of performance, but that's a judgement call we can't make for you.
exists is right next to existsSync in the manual and says:
Deprecated: Use fs.stat() or fs.access() instead.
So pick one of those.
access has an example:
// Check if the file exists in the current directory.
fs.access(file, fs.constants.F_OK, (err) => {
console.log(`${file} ${err ? 'does not exist' : 'exists'}`);
});

You can use existsSync as it's not deprecated. it's exists that got deprecated. I've attached a screenshot and link below so you can use it without any problem.
link->
https://nodejs.org/api/fs.html#fs_fs_existssync_path
image->

Modern async/await way
const isDirExist = async path => await fs.promises.access(path).then(()=>true).catch(()=>false);
Using
const isDirExist = async path => await fs.promises.access(path).then(()=>true).catch(()=>false);
(async () => {
console.log(await isDirExist('/my/path/'));
})()

From official docs https://nodejs.org/api/fs.html#fspromisesaccesspath-mode
fs.access will throw an error if file don't exist. So you will not have a boolean to check if file exist or not, like java does from ancient ages. You should use a try/catch:
var isDirExist = false;
try{
await fs.promises.access("/foo/bar");
isDirExist = true;
}catch(e){
isDirExist = false;
}
If this looks problematic, official docs says:
Using fsPromises.access() to check for the accessibility of a file before calling fsPromises.open() is not recommended. Doing so introduces a race condition, since other processes may change the file's state between the two calls. Instead, user code should open/read/write the file directly and handle the error raised if the file is not accessible.

If you use node-fs-extra you can utilize...
fs.ensureDir(dir[,options][,callback])
Which by definition...
Ensures that the directory exists. If the directory structure does not exist, it is created.
See also fs.ensureDirSync

The below code will check if the destination exists. If it doesn't exist, it'll create the destination as a directory. It will also create the parent directories if they don't exist (because of recursive: true). It does not use Sync functions and will not block requests if used in a web server.
const fs = require('fs');
const targetDirectory = 'your/path/here';
fs.mkdir(targetDirectory, { recursive: true }, (error) => {
if (!error) {
console.log('Directory successfully created, or it already exists.');
return;
}
switch (error.code) {
case 'EEXIST':
// Error:
// Requested location already exists, but it's not a directory.
break;
case 'ENOTDIR':
// Error:
// The parent hierarchy contains a file with the same name as the dir
// you're trying to create.
break;
default:
// Some other error like permission denied.
console.error(error);
break;
}
});
See: mkdir docs.

Related

Why await within async function doesn't work for fs modules?

I am trying to read a sample.json file through my js code. First my program checks for sample.json within every folder in the specified path. And it reads the sample.json if available and fetches the data. But the await used doesn't work as expected and simply passes the empty object to the calling function before the async functions completes it execution. I have attached the image for the issue.
async function getAvailableJson(filesPath) {
let detectedJson = {};
let folders = await fs.promises.readdir(filesPath);
folders.forEach(async function(folder) {
await fs.promises.access(path.join(filesPath, folder, "Sample.json")).then(async function() {
jsonData = await fs.promises.readFile(path.join(filesPath, folder ,"Sample.json"))
const directory = JSON.parse(jsonData)
const hashvalue = Hash.MD5(jsonData)
detectedJson[directory["dirName"]] = {
name: directory["dirName"],
version: directory["dirVersion"],
hash: hashvalue
}
console.log(detectedJson);
}).catch(function(err) {
if(err.code === "ENOENT")
{}
});
});
return detectedJson;
}
I don't want to use any sync functions since it creates unnecessary locks. I have also tried with fs.readdir, fs.access and fs.readFile functions. Could someone point out what I am doing wrong here since I am new to Node.js thanks in advance.
Sample Image
Change your .forEach() to use for/of instead and generally simplify by not mixing await and .then().
async function getAvailableJson(filesPath) {
let detectedJson = {};
let folders = await fs.promises.readdir(filesPath);
let detectedJson = {};
for (let folder of folders) {
let file = path.join(filesPath, folder, "Sample.json");
try {
let jsonData = await fs.promises.readFile(file);
const directory = JSON.parse(jsonData);
const hashvalue = Hash.MD5(jsonData);
detectedJson[directory["dirName"]] = {
name: directory["dirName"],
version: directory["dirVersion"],
hash: hashvalue
};
} catch (err) {
// silently skip any directories that don't have sample.json in them
// otherwise, throw the error to stop further processing
if (err.code !== "ENOENT") {
console.log(`Error on file ${file}`, err);
throw err;
}
}
console.log(detectedJson);
}
return detectedJson;
}
Summary of Changes:
Replace .forEach() with for/of.
Remove .then() and use only await.
Remove .catch() and use only try/catch.
Remove call to fs.promises.access() since the error can just be handled on fs.promises.readFile()
Add logging if the error is not ENOENT so you can see what the error is and what file it's on. You pretty much never want to silently eat an error with no logging. Though you may want to skip some particular errors, others must be logged. Rethrow errors that are not ENOENT so the caller will see them.
Declare and initialize all variables in use here as local variables.
.forEach() is not promise-aware so using await inside it does not pause the outer function at all. Instead, use a for/of loop which doesn't create the extra function scope and will allow await to pause the parent function.
Also, I consider .forEach() to be pretty much obsolete these days. It's not promise-aware. for/of is a more efficient and more generic way to iterate. And, there's no longer a need to create a new function scope using the .forEach() callback because we have block-scoped variables with let and const. I don't use it any more.
Also, I see no reason why you're preflighting things with fs.promises.access(). That just creates a race condition and you may as well just handle whatever error you get from fs.promises.readFile() as that will do the same thing without the race condition.
See also a related answer on a similar issue.

Check folder for file name with node.js? [duplicate]

How can I synchronously check, using node.js, if a file or directory exists?
The answer to this question has changed over the years. The current answer is here at the top, followed by the various answers over the years in chronological order:
Current Answer
You can use fs.existsSync():
const fs = require("fs"); // Or `import fs from "fs";` with ESM
if (fs.existsSync(path)) {
// Do something
}
It was deprecated for several years, but no longer is. From the docs:
Note that fs.exists() is deprecated, but fs.existsSync() is not. (The
callback parameter to fs.exists() accepts parameters that are
inconsistent with other Node.js callbacks. fs.existsSync() does not
use a callback.)
You've specifically asked for a synchronous check, but if you can use an asynchronous check instead (usually best with I/O), use fs.promises.access if you're using async functions or fs.access (since exists is deprecated) if not:
In an async function:
try {
await fs.promises.access("somefile");
// The check succeeded
} catch (error) {
// The check failed
}
Or with a callback:
fs.access("somefile", error => {
if (!error) {
// The check succeeded
} else {
// The check failed
}
});
Historical Answers
Here are the historical answers in chronological order:
Original answer from 2010
(stat/statSync or lstat/lstatSync)
Update September 2012
(exists/existsSync)
Update February 2015
(Noting impending deprecation of exists/existsSync, so we're probably back to stat/statSync or lstat/lstatSync)
Update December 2015
(There's also fs.access(path, fs.F_OK, function(){}) / fs.accessSync(path, fs.F_OK), but note that if the file/directory doesn't exist, it's an error; docs for fs.stat recommend using fs.access if you need to check for existence without opening)
Update December 2016
fs.exists() is still deprecated but fs.existsSync() is no longer deprecated. So you can safely use it now.
Original answer from 2010:
You can use statSync or lstatSync (docs link), which give you an fs.Stats object. In general, if a synchronous version of a function is available, it will have the same name as the async version with Sync at the end. So statSync is the synchronous version of stat; lstatSync is the synchronous version of lstat, etc.
lstatSync tells you both whether something exists, and if so, whether it's a file or a directory (or in some file systems, a symbolic link, block device, character device, etc.), e.g. if you need to know if it exists and is a directory:
var fs = require('fs');
try {
// Query the entry
stats = fs.lstatSync('/the/path');
// Is it a directory?
if (stats.isDirectory()) {
// Yes it is
}
}
catch (e) {
// ...
}
...and similarly, if it's a file, there's isFile; if it's a block device, there's isBlockDevice, etc., etc. Note the try/catch; it throws an error if the entry doesn't exist at all.
If you don't care what the entry is and only want to know whether it exists, you can use path.existsSync (or with latest, fs.existsSync) as noted by user618408:
var path = require('path');
if (path.existsSync("/the/path")) { // or fs.existsSync
// ...
}
It doesn't require a try/catch but gives you no information about what the thing is, just that it's there. path.existsSync was deprecated long ago.
Side note: You've expressly asked how to check synchronously, so I've used the xyzSync versions of the functions above. But wherever possible, with I/O, it really is best to avoid synchronous calls. Calls into the I/O subsystem take significant time from a CPU's point of view. Note how easy it is to call lstat rather than lstatSync:
// Is it a directory?
lstat('/the/path', function(err, stats) {
if (!err && stats.isDirectory()) {
// Yes it is
}
});
But if you need the synchronous version, it's there.
Update September 2012
The below answer from a couple of years ago is now a bit out of date. The current way is to use fs.existsSync to do a synchronous check for file/directory existence (or of course fs.exists for an asynchronous check), rather than the path versions below.
Example:
var fs = require('fs');
if (fs.existsSync(path)) {
// Do something
}
// Or
fs.exists(path, function(exists) {
if (exists) {
// Do something
}
});
Update February 2015
And here we are in 2015 and the Node docs now say that fs.existsSync (and fs.exists) "will be deprecated". (Because the Node folks think it's dumb to check whether something exists before opening it, which it is; but that's not the only reason for checking whether something exists!)
So we're probably back to the various stat methods... Until/unless this changes yet again, of course.
Update December 2015
Don't know how long it's been there, but there's also fs.access(path, fs.F_OK, ...) / fs.accessSync(path, fs.F_OK). And at least as of October 2016, the fs.stat documentation recommends using fs.access to do existence checks ("To check if a file exists without manipulating it afterwards, fs.access() is recommended."). But note that the access not being available is considered an error, so this would probably be best if you're expecting the file to be accessible:
var fs = require('fs');
try {
fs.accessSync(path, fs.F_OK);
// Do something
} catch (e) {
// It isn't accessible
}
// Or
fs.access(path, fs.F_OK, function(err) {
if (!err) {
// Do something
} else {
// It isn't accessible
}
});
Update December 2016
You can use fs.existsSync():
if (fs.existsSync(path)) {
// Do something
}
It was deprecated for several years, but no longer is. From the docs:
Note that fs.exists() is deprecated, but fs.existsSync() is not. (The
callback parameter to fs.exists() accepts parameters that are
inconsistent with other Node.js callbacks. fs.existsSync() does not
use a callback.)
Looking at the source, there's a synchronous version of path.exists - path.existsSync. Looks like it got missed in the docs.
Update:
path.exists and path.existsSync are now deprecated. Please use fs.exists and fs.existsSync.
Update 2016:
fs.exists and fs.existsSync have also been deprecated. Use fs.stat() or fs.access() instead.
Update 2019:
use fs.existsSync. It's not deprecated.
https://nodejs.org/api/fs.html#fs_fs_existssync_path
Using the currently recommended (as of 2015) APIs (per the Node docs), this is what I do:
var fs = require('fs');
function fileExists(filePath)
{
try
{
return fs.statSync(filePath).isFile();
}
catch (err)
{
return false;
}
}
In response to the EPERM issue raised by #broadband in the comments, that brings up a good point. fileExists() is probably not a good way to think about this in many cases, because fileExists() can't really promise a boolean return. You may be able to determine definitively that the file exists or doesn't exist, but you may also get a permissions error. The permissions error doesn't necessarily imply that the file exists, because you could lack permission to the directory containing the file on which you are checking. And of course there is the chance you could encounter some other error in checking for file existence.
So my code above is really doesFileExistAndDoIHaveAccessToIt(), but your question might be doesFileNotExistAndCouldICreateIt(), which would be completely different logic (that would need to account for an EPERM error, among other things).
While the fs.existsSync answer addresses the question asked here directly, that is often not going to be what you want (you don't just want to know if "something" exists at a path, you probably care about whether the "thing" that exists is a file or a directory).
The bottom line is that if you're checking to see if a file exists, you are probably doing that because you intend to take some action based on the result, and that logic (the check and/or subsequent action) should accommodate the idea that a thing found at that path may be a file or a directory, and that you may encounter EPERM or other errors in the process of checking.
Another Update
Needing an answer to this question myself I looked up the node docs, seems you should not be using fs.exists, instead use fs.open and use outputted error to detect if a file does not exist:
from the docs:
fs.exists() is an anachronism and exists only for historical reasons.
There should almost never be a reason to use it in your own code.
In particular, checking if a file exists before opening it is an
anti-pattern that leaves you vulnerable to race conditions: another
process may remove the file between the calls to fs.exists() and
fs.open(). Just open the file and handle the error when it's not
there.
http://nodejs.org/api/fs.html#fs_fs_exists_path_callback
I use below function to test if file exists. It catches also other exceptions. So in case there are rights issues e.g. chmod ugo-rwx filename or in Windows
Right Click -> Properties -> Security -> Advanced -> Permission entries: empty list .. function returns exception as it should. The file exists but we don't have rights to access it. It would be wrong to ignore this kinds of exceptions.
function fileExists(path) {
try {
return fs.statSync(path).isFile();
}
catch (e) {
if (e.code == 'ENOENT') { // no such file or directory. File really does not exist
console.log("File does not exist.");
return false;
}
console.log("Exception fs.statSync (" + path + "): " + e);
throw e; // something else went wrong, we don't have rights, ...
}
}
Exception output, nodejs errors documentation in case file doesn't exist:
{
[Error: ENOENT: no such file or directory, stat 'X:\\delsdfsdf.txt']
errno: -4058,
code: 'ENOENT',
syscall: 'stat',
path: 'X:\\delsdfsdf.txt'
}
Exception in case we don't have rights to the file, but exists:
{
[Error: EPERM: operation not permitted, stat 'X:\file.txt']
errno: -4048,
code: 'EPERM',
syscall: 'stat',
path: 'X:\\file.txt'
}
const fs = require('fs');
check in the function like below,
if(fs.existsSync(<path_that_need_to_be_checked>)){
// enter the code to excecute after the folder is there.
}
else{
// Below code to create the folder, if its not there
fs.mkdir('<folder_name>', cb function);
}
fs.exists() is deprecated dont use it https://nodejs.org/api/fs.html#fs_fs_exists_path_callback
You could implement the core nodejs way used at this:
https://github.com/nodejs/node-v0.x-archive/blob/master/lib/module.js#L86
function statPath(path) {
try {
return fs.statSync(path);
} catch (ex) {}
return false;
}
this will return the stats object then once you've got the stats object you could try
var exist = statPath('/path/to/your/file.js');
if(exist && exist.isFile()) {
// do something
}
Some answers here says that fs.exists and fs.existsSync are both deprecated. According to the docs this is no more true. Only fs.exists is deprected now:
Note that fs.exists() is deprecated, but fs.existsSync() is not. (The
callback parameter to fs.exists() accepts parameters that are
inconsistent with other Node.js callbacks. fs.existsSync() does not
use a callback.)
So you can safely use fs.existsSync() to synchronously check if a file exists.
The path module does not provide a synchronous version of path.exists so you have to trick around with the fs module.
Fastest thing I can imagine is using fs.realpathSync which will throw an error that you have to catch, so you need to make your own wrapper function with a try/catch.
Using fileSystem (fs) tests will trigger error objects, which you then would need to wrap in a try/catch statement. Save yourself some effort, and use a feature introduce in the 0.4.x branch.
var path = require('path');
var dirs = ['one', 'two', 'three'];
dirs.map(function(dir) {
path.exists(dir, function(exists) {
var message = (exists) ? dir + ': is a directory' : dir + ': is not a directory';
console.log(message);
});
});
updated asnwer for those people 'correctly' pointing out it doesnt directly answer the question, more bring an alternative option.
Sync solution:
fs.existsSync('filePath') also see docs here.
Returns true if the path exists, false otherwise.
Async Promise solution
In an async context you could just write the async version in sync method with using the await keyword. You can simply turn the async callback method into an promise like this:
function fileExists(path){
return new Promise((resolve, fail) => fs.access(path, fs.constants.F_OK,
(err, result) => err ? fail(err) : resolve(result))
//F_OK checks if file is visible, is default does no need to be specified.
}
async function doSomething() {
var exists = await fileExists('filePath');
if(exists){
console.log('file exists');
}
}
the docs on access().
This is already answered, but if you like installing modules you can use dtfe, which stands for
Does the file exist?
const dtfe = require('dtfe');
dtfe('package.json');
//=> true
You can use fs-extra (npm i fs-extra) and its fs.ensureFile or for a directory fs.ensureDir since fs.exists has been depricated and fs.access does not recommend that your edit that file after using it "Do not use fs.access() to check for the accessibility of a file before calling fs.open(), fs.readFile() or fs.writeFile(). Doing so introduces a race condition, since other processes may change the file's state between the two calls. Instead, user code should open/read/write the file directly and handle the error raised if the file is not accessible."
The documents on fs.stat() says to use fs.access() if you are not going to manipulate the file. It did not give a justification, might be faster or less memeory use?
I use node for linear automation, so I thought I share the function I use to test for file existence.
var fs = require("fs");
function exists(path){
//Remember file access time will slow your program.
try{
fs.accessSync(path);
} catch (err){
return false;
}
return true;
}
❄️ You can use graph-fs
directory.exists // boolean
Here is a simple wrapper solution for this:
var fs = require('fs')
function getFileRealPath(s){
try {return fs.realpathSync(s);} catch(e){return false;}
}
Usage:
Works for both directories and files
If item exists, it returns the path to the file or directory
If item does not exist, it returns false
Example:
var realPath,pathToCheck='<your_dir_or_file>'
if( (realPath=getFileRealPath(pathToCheck)) === false){
console.log('file/dir not found: '+pathToCheck);
} else {
console.log('file/dir exists: '+realPath);
}
Make sure you use === operator to test if return equals false. There is no logical reason that fs.realpathSync() would return false under proper working conditions so I think this should work 100%.
I would prefer to see a solution that does not does not generate an Error and resulting performance hit. From an API perspective, fs.exists() seems like the most elegant solution.
From the answers it appears that there is no official API support for this (as in a direct and explicit check). Many of the answers say to use stat, however they are not strict. We can't assume for example that any error thrown by stat means that something doesn't exist.
Lets say we try it with something that doesn't exist:
$ node -e 'require("fs").stat("god",err=>console.log(err))'
{ Error: ENOENT: no such file or directory, stat 'god' errno: -2, code: 'ENOENT', syscall: 'stat', path: 'god' }
Lets try it with something that exists but that we don't have access to:
$ mkdir -p fsm/appendage && sudo chmod 0 fsm
$ node -e 'require("fs").stat("fsm/appendage",err=>console.log(err))'
{ Error: EACCES: permission denied, stat 'access/access' errno: -13, code: 'EACCES', syscall: 'stat', path: 'fsm/appendage' }
At the very least you'll want:
let dir_exists = async path => {
let stat;
try {
stat = await (new Promise(
(resolve, reject) => require('fs').stat(path,
(err, result) => err ? reject(err) : resolve(result))
));
}
catch(e) {
if(e.code === 'ENOENT') return false;
throw e;
}
if(!stat.isDirectory())
throw new Error('Not a directory.');
return true;
};
The question is not clear on if you actually want it to be syncronous or if you only want it to be written as though it is syncronous. This example uses await/async so that it is only written syncronously but runs asyncronously.
This means you have to call it as such at the top level:
(async () => {
try {
console.log(await dir_exists('god'));
console.log(await dir_exists('fsm/appendage'));
}
catch(e) {
console.log(e);
}
})();
An alternative is using .then and .catch on the promise returned from the async call if you need it further down.
If you want to check if something exists then it's a good practice to also ensure it's the right type of thing such as a directory or file. This is included in the example. If it's not allowed to be a symlink you must use lstat instead of stat as stat will automatically traverse links.
You can replace all of the async to sync code in here and use statSync instead. However expect that once async and await become universally supports the Sync calls will become redundant eventually to be depreciated (otherwise you would have to define them everywhere and up the chain just like with async making it really pointless).
Chances are, if you want to know if a file exists, you plan to require it if it does.
function getFile(path){
try{
return require(path);
}catch(e){
return false;
}
}

node.js fs.exists() will be deprecated, what to use instead?

According to the documentation node.js fs.exists() will be deprecated.
Their reasoning:
fs.exists() is an anachronism and exists only for historical reasons. There should almost never be a reason to use it in your own code.
In particular, checking if a file exists before opening it is an anti-pattern that leaves you vulnerable to race conditions: another process may remove the file between the calls to fs.exists() and fs.open(). Just open the file and handle the error when it's not there.
fs.exists() will be deprecated.
I am currently using it before moving files, since the fs.rename() seems to quietly overwrite files with the same name in the destination folder.
My question is; what should I use instead to prevent fs.rename() from overwriting the file in the destination folder?
I assume there's a way that I don't know of. Otherwise I don't see a reason for fs.exists() to be deprecated.
Using fs.open() as suggested seems overkill since I don't want to open the file.
Edit, as per #jfriend00's request for more info about what I'm doing.
I'm making an Electron application where the user can sort files into different directories. It's not a server software, it's intended to run on every day users machines, handling their documents. This is the code so far for moving a file:
function moveFile(destIndex){
var from = queue[currentQueueIndex].path;
var to = destinations[destIndex].path + path.sep + path.basename(from);
console.log("[i] Move file (from/to): ");
console.log(from);
console.log(to);
//Check if file exists, if yes: give them the choice to cancel.
fs.stat(to, function (err, stats) {
if (err){
move(from, to);
} else {
var confirmed = confirm("File already exists, will overwrite.");
if (confirmed) {
move(from, to);
}
}
});
next(); //Show the next file to the user
}
function move(from, to){
fs.rename(from, to, function (err) {
if (err) throw err;
console.log('[i] Move successful');
queue[currentQueueIndex].path = to;
queue[currentQueueIndex].moved = true;
});
}
After the first comment, the part starting with fs.stat, I check whether the file I'm about to create with fs.rename already exists. I guess this is subject to race conditions, but I can't find that fs.rename handles duplicates in any way.
Since this application is intended for "home computing", I don't think the scenario where a file disappears between the stat check and the rename is likely to happen. But still, the more potential problems I can avoid, the better.
Use fs.existsSync().
fs.existsSync() has not been deprecated.
https://nodejs.org/api/fs.html#fs_fs_existssync_path
fs.existsSync(path)
Added in: v0.1.21
path |
Synchronous version of fs.exists(). Returns true if the file exists, false otherwise.
Note that fs.exists() is deprecated, but fs.existsSync() is not. (The callback >parameter to fs.exists() accepts parameters that are inconsistent with other >Node.js callbacks. fs.existsSync() does not use a callback.)
The io.js docs mention the use of fs.stat() or fs.access() in place of fs.exists().
Here is an example using fs.access (in older Node versions, use fs.stat instead of fs.access), but handling errors correctly as well:
import { access } from 'node:fs/promises';
async function fileExists(filename) {
try {
await access(filename);
return true;
} catch (err) {
if (err.code === 'ENOENT') {
return false;
} else {
throw err;
}
}
}
Here is example by using fs.stat:-
fs.stat('mycustomfile.csv', function (err, stats) {
console.log(stats);//here we got all information of file in stats variable
if (err) {
return console.error(err);
}
fs.unlink('mycustomfile.csv',function(err){
if(err) return console.log(err);
console.log('file deleted successfully');
});
});
const exists = !!(await fs.promises.stat(filename).catch(() => null))

Creating a file only if it doesn't exist in Node.js

We have a buffer we'd like to write to a file. If the file already exists, we need to increment an index on it, and try again. Is there a way to create a file only if it doesn't exist, or should I just stat files until I get an error to find one that doesn't exist already?
For example, I have files a_1.jpg and a_2.jpg. I'd like my method to try creating a_1.jpg and a_2.jpg, and fail, and finally successfully create a_3.jpg.
The ideal method would look something like this:
fs.writeFile(path, data, { overwrite: false }, function (err) {
if (err) throw err;
console.log('It\'s saved!');
});
or like this:
fs.createWriteStream(path, { overwrite: false });
Does anything like this exist in node's fs library?
EDIT: My question isn't if there's a separate function that checks for existence. It's this: is there a way to create a file if it doesn't exist, in a single file system call?
As your intuition correctly guessed, the naive solution with a pair of exists / writeFile calls is wrong. Asynchronous code runs in unpredictable ways. And in given case it is
Is there a file a.txt? — No.
(File a.txt gets created by another program)
Write to a.txt if it's possible. — Okay.
But yes, we can do that in a single call. We're working with file system so it's a good idea to read developer manual on fs. And hey, here's an interesting part.
'w' - Open file for writing. The file is created (if it does not
exist) or truncated (if it exists).
'wx' - Like 'w' but fails if path exists.
So all we have to do is just add wx to the fs.open call. But hey, we don't like fopen-like IO. Let's read on fs.writeFile a bit more.
fs.readFile(filename[, options], callback)#
filename String
options Object
encoding String | Null default = null
flag String default = 'r'
callback Function
That options.flag looks promising. So we try
fs.writeFile(path, data, { flag: 'wx' }, function (err) {
if (err) throw err;
console.log("It's saved!");
});
And it works perfectly for a single write. I guess this code will fail in some more bizarre ways yet if you try to solve your task with it. You have an atomary "check for a_#.jpg existence, and write there if it's empty" operation, but all the other fs state is not locked, and a_1.jpg file may spontaneously disappear while you're already checking a_5.jpg. Most* file systems are no ACID databases, and the fact that you're able to do at least some atomic operations is miraculous. It's very likely that wx code won't work on some platform. So for the sake of your sanity, use database, finally.
Some more info for the suffering
Imagine we're writing something like memoize-fs that caches results of function calls to the file system to save us some network/cpu time. Could we open the file for reading if it exists, and for writing if it doesn't, all in the single call? Let's take a funny look on those flags. After a while of mental exercises we can see that a+ does what we want: if the file doesn't exist, it creates one and opens it both for reading and writing, and if the file exists it does so without clearing the file (as w+ would). But now we cannot use it neither in (smth)File, nor in create(Smth)Stream functions. And that seems like a missing feature.
So feel free to file it as a feature request (or even a bug) to Node.js github, as lack of atomic asynchronous file system API is a drawback of Node. Though don't expect changes any time soon.
Edit. I would like to link to articles by Linus and by Dan Luu on why exactly you don't want to do anything smart with your fs calls, because the claim was left mostly not based on anything.
What about using the a option?
According to the docs:
'a+' - Open file for reading and appending. The file is created if it does not exist.
It seems to work perfectly with createWriteStream
This method is no longer recommended. fs.exists is deprecated. See comments.
Here are some options:
1) Have 2 "fs" calls. The first one is the "fs.exists" call, and the second is "fs.write / read, etc"
//checks if the file exists.
//If it does, it just calls back.
//If it doesn't, then the file is created.
function checkForFile(fileName,callback)
{
fs.exists(fileName, function (exists) {
if(exists)
{
callback();
}else
{
fs.writeFile(fileName, {flag: 'wx'}, function (err, data)
{
callback();
})
}
});
}
function writeToFile()
{
checkForFile("file.dat",function()
{
//It is now safe to write/read to file.dat
fs.readFile("file.dat", function (err,data)
{
//do stuff
});
});
}
2) Or Create an empty file first:
--- Sync:
//If you want to force the file to be empty then you want to use the 'w' flag:
var fd = fs.openSync(filepath, 'w');
//That will truncate the file if it exists and create it if it doesn't.
//Wrap it in an fs.closeSync call if you don't need the file descriptor it returns.
fs.closeSync(fs.openSync(filepath, 'w'));
--- ASync:
var fs = require("fs");
fs.open(path, "wx", function (err, fd) {
// handle error
fs.close(fd, function (err) {
// handle error
});
});
3) Or use "touch": https://github.com/isaacs/node-touch
Todo this in a single system call you can use the fs-extra npm module.
After this the file will have been created as well as the directory it is to be placed in.
const fs = require('fs-extra');
const file = '/tmp/this/path/does/not/exist/file.txt'
fs.ensureFile(file, err => {
console.log(err) // => null
});
Another way is to use ensureFileSync which will do the same thing but synchronous.
const fs = require('fs-extra');
const file = '/tmp/this/path/does/not/exist/file.txt'
fs.ensureFileSync(file)
With async / await and Typescript I would do:
import * as fs from 'fs'
async function upsertFile(name: string) {
try {
// try to read file
await fs.promises.readFile(name)
} catch (error) {
// create empty file, because it wasn't found
await fs.promises.writeFile(name, '')
}
}
Here's a synchronous way of doing it:
try {
await fs.truncateSync(filepath, 0);
} catch (err) {
await fs.writeFileSync(filepath, "", { flag: "wx" });
}
If the file exists it will get truncated, otherwise it gets created if an error is raised.
This works for me.
// Use the file system fs promises
const {access} = require('fs/promises');
// File Exist returns true
// dont use exists which is no more!
const fexists =async (path)=> {
try {
await access(path);
return true;
} catch {
return false;
}
}
// Wrapper for your main program
async function mainapp(){
if( await fexists("./users.json")){
console.log("File is here");
} else {
console.log("File not here -so make one");
}
}
// run your program
mainapp();
Just keep eye on your async - awaits so everthing plays nice.
hope this helps.
You can do something like this:
function writeFile(i){
var i = i || 0;
var fileName = 'a_' + i + '.jpg';
fs.exists(fileName, function (exists) {
if(exists){
writeFile(++i);
} else {
fs.writeFile(fileName);
}
});
}

Check synchronously if file/directory exists in Node.js

How can I synchronously check, using node.js, if a file or directory exists?
The answer to this question has changed over the years. The current answer is here at the top, followed by the various answers over the years in chronological order:
Current Answer
You can use fs.existsSync():
const fs = require("fs"); // Or `import fs from "fs";` with ESM
if (fs.existsSync(path)) {
// Do something
}
It was deprecated for several years, but no longer is. From the docs:
Note that fs.exists() is deprecated, but fs.existsSync() is not. (The
callback parameter to fs.exists() accepts parameters that are
inconsistent with other Node.js callbacks. fs.existsSync() does not
use a callback.)
You've specifically asked for a synchronous check, but if you can use an asynchronous check instead (usually best with I/O), use fs.promises.access if you're using async functions or fs.access (since exists is deprecated) if not:
In an async function:
try {
await fs.promises.access("somefile");
// The check succeeded
} catch (error) {
// The check failed
}
Or with a callback:
fs.access("somefile", error => {
if (!error) {
// The check succeeded
} else {
// The check failed
}
});
Historical Answers
Here are the historical answers in chronological order:
Original answer from 2010
(stat/statSync or lstat/lstatSync)
Update September 2012
(exists/existsSync)
Update February 2015
(Noting impending deprecation of exists/existsSync, so we're probably back to stat/statSync or lstat/lstatSync)
Update December 2015
(There's also fs.access(path, fs.F_OK, function(){}) / fs.accessSync(path, fs.F_OK), but note that if the file/directory doesn't exist, it's an error; docs for fs.stat recommend using fs.access if you need to check for existence without opening)
Update December 2016
fs.exists() is still deprecated but fs.existsSync() is no longer deprecated. So you can safely use it now.
Original answer from 2010:
You can use statSync or lstatSync (docs link), which give you an fs.Stats object. In general, if a synchronous version of a function is available, it will have the same name as the async version with Sync at the end. So statSync is the synchronous version of stat; lstatSync is the synchronous version of lstat, etc.
lstatSync tells you both whether something exists, and if so, whether it's a file or a directory (or in some file systems, a symbolic link, block device, character device, etc.), e.g. if you need to know if it exists and is a directory:
var fs = require('fs');
try {
// Query the entry
stats = fs.lstatSync('/the/path');
// Is it a directory?
if (stats.isDirectory()) {
// Yes it is
}
}
catch (e) {
// ...
}
...and similarly, if it's a file, there's isFile; if it's a block device, there's isBlockDevice, etc., etc. Note the try/catch; it throws an error if the entry doesn't exist at all.
If you don't care what the entry is and only want to know whether it exists, you can use path.existsSync (or with latest, fs.existsSync) as noted by user618408:
var path = require('path');
if (path.existsSync("/the/path")) { // or fs.existsSync
// ...
}
It doesn't require a try/catch but gives you no information about what the thing is, just that it's there. path.existsSync was deprecated long ago.
Side note: You've expressly asked how to check synchronously, so I've used the xyzSync versions of the functions above. But wherever possible, with I/O, it really is best to avoid synchronous calls. Calls into the I/O subsystem take significant time from a CPU's point of view. Note how easy it is to call lstat rather than lstatSync:
// Is it a directory?
lstat('/the/path', function(err, stats) {
if (!err && stats.isDirectory()) {
// Yes it is
}
});
But if you need the synchronous version, it's there.
Update September 2012
The below answer from a couple of years ago is now a bit out of date. The current way is to use fs.existsSync to do a synchronous check for file/directory existence (or of course fs.exists for an asynchronous check), rather than the path versions below.
Example:
var fs = require('fs');
if (fs.existsSync(path)) {
// Do something
}
// Or
fs.exists(path, function(exists) {
if (exists) {
// Do something
}
});
Update February 2015
And here we are in 2015 and the Node docs now say that fs.existsSync (and fs.exists) "will be deprecated". (Because the Node folks think it's dumb to check whether something exists before opening it, which it is; but that's not the only reason for checking whether something exists!)
So we're probably back to the various stat methods... Until/unless this changes yet again, of course.
Update December 2015
Don't know how long it's been there, but there's also fs.access(path, fs.F_OK, ...) / fs.accessSync(path, fs.F_OK). And at least as of October 2016, the fs.stat documentation recommends using fs.access to do existence checks ("To check if a file exists without manipulating it afterwards, fs.access() is recommended."). But note that the access not being available is considered an error, so this would probably be best if you're expecting the file to be accessible:
var fs = require('fs');
try {
fs.accessSync(path, fs.F_OK);
// Do something
} catch (e) {
// It isn't accessible
}
// Or
fs.access(path, fs.F_OK, function(err) {
if (!err) {
// Do something
} else {
// It isn't accessible
}
});
Update December 2016
You can use fs.existsSync():
if (fs.existsSync(path)) {
// Do something
}
It was deprecated for several years, but no longer is. From the docs:
Note that fs.exists() is deprecated, but fs.existsSync() is not. (The
callback parameter to fs.exists() accepts parameters that are
inconsistent with other Node.js callbacks. fs.existsSync() does not
use a callback.)
Looking at the source, there's a synchronous version of path.exists - path.existsSync. Looks like it got missed in the docs.
Update:
path.exists and path.existsSync are now deprecated. Please use fs.exists and fs.existsSync.
Update 2016:
fs.exists and fs.existsSync have also been deprecated. Use fs.stat() or fs.access() instead.
Update 2019:
use fs.existsSync. It's not deprecated.
https://nodejs.org/api/fs.html#fs_fs_existssync_path
Using the currently recommended (as of 2015) APIs (per the Node docs), this is what I do:
var fs = require('fs');
function fileExists(filePath)
{
try
{
return fs.statSync(filePath).isFile();
}
catch (err)
{
return false;
}
}
In response to the EPERM issue raised by #broadband in the comments, that brings up a good point. fileExists() is probably not a good way to think about this in many cases, because fileExists() can't really promise a boolean return. You may be able to determine definitively that the file exists or doesn't exist, but you may also get a permissions error. The permissions error doesn't necessarily imply that the file exists, because you could lack permission to the directory containing the file on which you are checking. And of course there is the chance you could encounter some other error in checking for file existence.
So my code above is really doesFileExistAndDoIHaveAccessToIt(), but your question might be doesFileNotExistAndCouldICreateIt(), which would be completely different logic (that would need to account for an EPERM error, among other things).
While the fs.existsSync answer addresses the question asked here directly, that is often not going to be what you want (you don't just want to know if "something" exists at a path, you probably care about whether the "thing" that exists is a file or a directory).
The bottom line is that if you're checking to see if a file exists, you are probably doing that because you intend to take some action based on the result, and that logic (the check and/or subsequent action) should accommodate the idea that a thing found at that path may be a file or a directory, and that you may encounter EPERM or other errors in the process of checking.
Another Update
Needing an answer to this question myself I looked up the node docs, seems you should not be using fs.exists, instead use fs.open and use outputted error to detect if a file does not exist:
from the docs:
fs.exists() is an anachronism and exists only for historical reasons.
There should almost never be a reason to use it in your own code.
In particular, checking if a file exists before opening it is an
anti-pattern that leaves you vulnerable to race conditions: another
process may remove the file between the calls to fs.exists() and
fs.open(). Just open the file and handle the error when it's not
there.
http://nodejs.org/api/fs.html#fs_fs_exists_path_callback
I use below function to test if file exists. It catches also other exceptions. So in case there are rights issues e.g. chmod ugo-rwx filename or in Windows
Right Click -> Properties -> Security -> Advanced -> Permission entries: empty list .. function returns exception as it should. The file exists but we don't have rights to access it. It would be wrong to ignore this kinds of exceptions.
function fileExists(path) {
try {
return fs.statSync(path).isFile();
}
catch (e) {
if (e.code == 'ENOENT') { // no such file or directory. File really does not exist
console.log("File does not exist.");
return false;
}
console.log("Exception fs.statSync (" + path + "): " + e);
throw e; // something else went wrong, we don't have rights, ...
}
}
Exception output, nodejs errors documentation in case file doesn't exist:
{
[Error: ENOENT: no such file or directory, stat 'X:\\delsdfsdf.txt']
errno: -4058,
code: 'ENOENT',
syscall: 'stat',
path: 'X:\\delsdfsdf.txt'
}
Exception in case we don't have rights to the file, but exists:
{
[Error: EPERM: operation not permitted, stat 'X:\file.txt']
errno: -4048,
code: 'EPERM',
syscall: 'stat',
path: 'X:\\file.txt'
}
const fs = require('fs');
check in the function like below,
if(fs.existsSync(<path_that_need_to_be_checked>)){
// enter the code to excecute after the folder is there.
}
else{
// Below code to create the folder, if its not there
fs.mkdir('<folder_name>', cb function);
}
fs.exists() is deprecated dont use it https://nodejs.org/api/fs.html#fs_fs_exists_path_callback
You could implement the core nodejs way used at this:
https://github.com/nodejs/node-v0.x-archive/blob/master/lib/module.js#L86
function statPath(path) {
try {
return fs.statSync(path);
} catch (ex) {}
return false;
}
this will return the stats object then once you've got the stats object you could try
var exist = statPath('/path/to/your/file.js');
if(exist && exist.isFile()) {
// do something
}
Some answers here says that fs.exists and fs.existsSync are both deprecated. According to the docs this is no more true. Only fs.exists is deprected now:
Note that fs.exists() is deprecated, but fs.existsSync() is not. (The
callback parameter to fs.exists() accepts parameters that are
inconsistent with other Node.js callbacks. fs.existsSync() does not
use a callback.)
So you can safely use fs.existsSync() to synchronously check if a file exists.
The path module does not provide a synchronous version of path.exists so you have to trick around with the fs module.
Fastest thing I can imagine is using fs.realpathSync which will throw an error that you have to catch, so you need to make your own wrapper function with a try/catch.
Using fileSystem (fs) tests will trigger error objects, which you then would need to wrap in a try/catch statement. Save yourself some effort, and use a feature introduce in the 0.4.x branch.
var path = require('path');
var dirs = ['one', 'two', 'three'];
dirs.map(function(dir) {
path.exists(dir, function(exists) {
var message = (exists) ? dir + ': is a directory' : dir + ': is not a directory';
console.log(message);
});
});
updated asnwer for those people 'correctly' pointing out it doesnt directly answer the question, more bring an alternative option.
Sync solution:
fs.existsSync('filePath') also see docs here.
Returns true if the path exists, false otherwise.
Async Promise solution
In an async context you could just write the async version in sync method with using the await keyword. You can simply turn the async callback method into an promise like this:
function fileExists(path){
return new Promise((resolve, fail) => fs.access(path, fs.constants.F_OK,
(err, result) => err ? fail(err) : resolve(result))
//F_OK checks if file is visible, is default does no need to be specified.
}
async function doSomething() {
var exists = await fileExists('filePath');
if(exists){
console.log('file exists');
}
}
the docs on access().
This is already answered, but if you like installing modules you can use dtfe, which stands for
Does the file exist?
const dtfe = require('dtfe');
dtfe('package.json');
//=> true
You can use fs-extra (npm i fs-extra) and its fs.ensureFile or for a directory fs.ensureDir since fs.exists has been depricated and fs.access does not recommend that your edit that file after using it "Do not use fs.access() to check for the accessibility of a file before calling fs.open(), fs.readFile() or fs.writeFile(). Doing so introduces a race condition, since other processes may change the file's state between the two calls. Instead, user code should open/read/write the file directly and handle the error raised if the file is not accessible."
The documents on fs.stat() says to use fs.access() if you are not going to manipulate the file. It did not give a justification, might be faster or less memeory use?
I use node for linear automation, so I thought I share the function I use to test for file existence.
var fs = require("fs");
function exists(path){
//Remember file access time will slow your program.
try{
fs.accessSync(path);
} catch (err){
return false;
}
return true;
}
❄️ You can use graph-fs
directory.exists // boolean
Here is a simple wrapper solution for this:
var fs = require('fs')
function getFileRealPath(s){
try {return fs.realpathSync(s);} catch(e){return false;}
}
Usage:
Works for both directories and files
If item exists, it returns the path to the file or directory
If item does not exist, it returns false
Example:
var realPath,pathToCheck='<your_dir_or_file>'
if( (realPath=getFileRealPath(pathToCheck)) === false){
console.log('file/dir not found: '+pathToCheck);
} else {
console.log('file/dir exists: '+realPath);
}
Make sure you use === operator to test if return equals false. There is no logical reason that fs.realpathSync() would return false under proper working conditions so I think this should work 100%.
I would prefer to see a solution that does not does not generate an Error and resulting performance hit. From an API perspective, fs.exists() seems like the most elegant solution.
From the answers it appears that there is no official API support for this (as in a direct and explicit check). Many of the answers say to use stat, however they are not strict. We can't assume for example that any error thrown by stat means that something doesn't exist.
Lets say we try it with something that doesn't exist:
$ node -e 'require("fs").stat("god",err=>console.log(err))'
{ Error: ENOENT: no such file or directory, stat 'god' errno: -2, code: 'ENOENT', syscall: 'stat', path: 'god' }
Lets try it with something that exists but that we don't have access to:
$ mkdir -p fsm/appendage && sudo chmod 0 fsm
$ node -e 'require("fs").stat("fsm/appendage",err=>console.log(err))'
{ Error: EACCES: permission denied, stat 'access/access' errno: -13, code: 'EACCES', syscall: 'stat', path: 'fsm/appendage' }
At the very least you'll want:
let dir_exists = async path => {
let stat;
try {
stat = await (new Promise(
(resolve, reject) => require('fs').stat(path,
(err, result) => err ? reject(err) : resolve(result))
));
}
catch(e) {
if(e.code === 'ENOENT') return false;
throw e;
}
if(!stat.isDirectory())
throw new Error('Not a directory.');
return true;
};
The question is not clear on if you actually want it to be syncronous or if you only want it to be written as though it is syncronous. This example uses await/async so that it is only written syncronously but runs asyncronously.
This means you have to call it as such at the top level:
(async () => {
try {
console.log(await dir_exists('god'));
console.log(await dir_exists('fsm/appendage'));
}
catch(e) {
console.log(e);
}
})();
An alternative is using .then and .catch on the promise returned from the async call if you need it further down.
If you want to check if something exists then it's a good practice to also ensure it's the right type of thing such as a directory or file. This is included in the example. If it's not allowed to be a symlink you must use lstat instead of stat as stat will automatically traverse links.
You can replace all of the async to sync code in here and use statSync instead. However expect that once async and await become universally supports the Sync calls will become redundant eventually to be depreciated (otherwise you would have to define them everywhere and up the chain just like with async making it really pointless).
Chances are, if you want to know if a file exists, you plan to require it if it does.
function getFile(path){
try{
return require(path);
}catch(e){
return false;
}
}

Resources