0

Im trying to check the file system on my server to check if a file exists or not. This simple problem became actually quite a challenging task. Here is my basic code which does not work:

  var fs = require('fs');
  var arrayLength = arr.length;
  for (var i = 0; i < arrayLength; i++) {
    var imgfile = arr[i].country
    fs.exists('/var/scraper/public/images/flags' + imgfile + ".png", (exists) => {
      console.log(exists ? 'it\'s there' : 'not here!');
    });                    
  }   

Its come to my attention that this is not asynchronous and will not work. I found this link: https://nodejs.org/dist/latest-v9.x/docs/api/fs.html#fs_fs_exists_path_callback

and my code should be built like this.

fs.open('myfile', 'wx', (err, fd) => {
  if (err) {
    if (err.code === 'EEXIST') {
      console.error('myfile already exists');
      return;
    }

    throw err;
  }

  writeMyData(fd);
 });

I was hoping to get some help to help me rewrite my code to make it asynchronous?

any help at all with this would be much appreciated.

Frederik 84
  • 61
  • 2
  • 15
  • 1
    What do you mean " is not asynchronous and will not work"? Why will it not work? – Sergio Tulentsev Mar 24 '18 at 08:24
  • well it does not work when I run it in nodejs to be honest I dont know what "asynchronous " means so that really makes my problem difficult – Frederik 84 Mar 24 '18 at 08:36
  • when I run my first code it does not find any file in that directory however the directory should be correct. Ive been struggling to how to make this work for quite some time now. – Frederik 84 Mar 24 '18 at 08:41
  • Synchronous code works perfectly well in Node.js, generally we use asynchronous calls for any i/o. This is generally too ensure the efficient use of resources rather than anything else. – Terry Lennox Mar 24 '18 at 08:45

2 Answers2

1

You can do this synchronously with no problem, it might just take awile. If the fs.exists function is not finding a file I'd just ensure your path is exactly correct. I added an extra '/' after /flags as I'm assuming the array of country names does not include this.

const fs = require('fs');
const path = require('path');
const imageDir = '/var/scraper/public/images/flags/';

var filesExist = arr.map((imgObj) => {
  const imgfile = imgObj.country;
  let filePath = path.join(imageDir, imgfile + ".png");
  console.log('Checking existance of file: ', filePath);
  // Return an object with 'exists' property and also the file path
  // To just return the path:
  // return fs.existsSync(filePath) ? filePath: path.join(imageDir, "noimg.png")};
  return { exists: fs.existsSync(filePath), path: fs.existsSync(filePath) ? filePath: path.join(imageDir, "noimg.png")};
});

console.log('Files exist: ', filesExist);
Terry Lennox
  • 29,471
  • 5
  • 28
  • 40
  • Hi thanks for your reply . this code looks quite promising. my knowledge with this i quite low imo. If you look in my post #1 how would I make your code loop trough my array to check each and every instance? – Frederik 84 Mar 24 '18 at 08:49
  • Hey @Frederik84, the answer I posted will loop through the arr array. This is what arr.map does. It calls fs.existsSync for each entry in the array. array.map, array.reduce are very powerful! – Terry Lennox Mar 24 '18 at 08:50
  • but how would I set the imgfile var using your code ? – Frederik 84 Mar 24 '18 at 09:05
  • The imgFile variable will be set for each entry in the arr array. arr.map will populate it! – Terry Lennox Mar 24 '18 at 09:07
  • You can always do a console.log in the arr.map code.. I'll update with an example! – Terry Lennox Mar 24 '18 at 09:07
  • Ill try to just copy your code and test . I received way more answers that I expected on this post , Im very grateful for that I had to put my project on hold while trying to figure this out. – Frederik 84 Mar 24 '18 at 09:16
  • 1
    We're here to help! Good luck with your testing. Node.js can be a little tricky to learn but it's a great technology! – Terry Lennox Mar 24 '18 at 09:18
  • Your code (so far) is the only one I have been able to get somewhat to working. t did indeed loop trough everything. However it return this: Checking existance of file: /var/scraper/public/images/flags/[object Object].png its should return the file name instead of object object – Frederik 84 Mar 24 '18 at 09:20
  • Im not sure if you edited your post or not. But did a 2nd test and now its working perfectly. That is just great. Thanks a lot for your help with this. 2 thumbs way up !!! – Frederik 84 Mar 24 '18 at 10:16
  • Great, I did edit the post ( based on another user spotting the error!), glad it works now! – Terry Lennox Mar 24 '18 at 10:18
  • just a quick follow up if you don't mind ? now it returns true or false , how can i make it return full file path + exists/exists not – Frederik 84 Mar 24 '18 at 10:19
  • my ultimate goal with this code was to add to the array filepath for img when found , and when not found it should add noimg.png to the filepath instead. but this was great start to get me going – Frederik 84 Mar 24 '18 at 10:21
  • It should be easy to do this in the same arr.map call. I'll update the answer!! – Terry Lennox Mar 24 '18 at 10:28
  • thanks I would imagine it to be easy. I just need to understand how this great code works and how to edit it to suit my needs.. – Frederik 84 Mar 24 '18 at 10:33
  • Ok so its in the "return" the magic happens? perfect! you have been brilliant and great.am I pushing your friendliness it if I ask how I can add this info into another col in .arr var ? – Frederik 84 Mar 24 '18 at 10:38
  • Yes, in the return statement you create the array of objects returned. I updated the answer to include the path, I think this should do the job! – Terry Lennox Mar 24 '18 at 10:39
  • 1
    No problemo!! Node is great :) – Terry Lennox Mar 24 '18 at 10:45
  • Hi I had one more question at this point your code returns like this: { Logopath: '/var/scraper/public/images/flags/Italy.png' } How can this be modified so it only returns: /var/scraper/public/images/flags/Italy.png – Frederik 84 Mar 25 '18 at 17:08
  • 1
    I'll update the answer, you just want the path, is that right? – Terry Lennox Mar 25 '18 at 17:11
  • that is correct , it will be easier to work with , I tried str.replace also but had some trouble since this var is an object. Thanks alot – Frederik 84 Mar 25 '18 at 17:15
  • I've updated the answer with this, it's just in a comment line, ta! – Terry Lennox Mar 25 '18 at 17:17
  • thanks alot sir I've been struggling with this since you posted it yesterday :=) this was great – Frederik 84 Mar 25 '18 at 17:23
1

The simplest and lease time consuming solution to this problem would be to simply use fs.existsSync You can find docs for that method here. In fact, if you take a look at fs.exists in the docs you'll notice that fs.exists has been deprecated at least since the last v8 LTS release (this might be why you are having trouble with it).

If you are using a recent version of node with support for it, this is a great opportunity to leverage async/await. It might look something like this:

const fs = require('fs');
const { promisify } = require('util');
const existsAsync = promisify(fs.exists);

async function checkFiles (arr) {
  const arrayLength = arr.length;

  for (let i = 0; I < arrayLength; I++) {
    const countryName = arr[i].country;

    const filePath = `/var/scraper/public/images/flags${countryName}.png`; 
    const fileExists = await fs.existsAsync(filePath);

    console.log(`File flags${contryName}.png exists: ${fileExists}`);
  }
}
Bryson Reynolds
  • 191
  • 1
  • 12
  • "has been deprecated at least since the last v8 LTS release (this might be why you are having trouble with it)." - yes that and synchronous/asynchronous calls got my head spinning , lol Thanks for your answer Ill try to test it right away – Frederik 84 Mar 24 '18 at 08:54
  • also as a small side questio: what is the difference betwen const and var ? – Frederik 84 Mar 24 '18 at 09:00
  • 1
    const defines a variable that will not change. It's useful when using the require statement for example. – Terry Lennox Mar 24 '18 at 09:01
  • but for some reason im not able to get this code work I get this error code: " Unexpected token ( -bash: syntax error near unexpected token `(' " error starts here; async function (arr) { , Im sure its me that have done something wrong – Frederik 84 Mar 24 '18 at 09:10
  • 1
    Ultimately `const` creates an immutable binding to the assigned value thus preventing the ability to mutate it. On the other hand, `let` is very similar to `var` except that `let` is constrained to block scope while `var` is constrained to an entire function regardless of with no regard to block scope. [Here](https://stackoverflow.com/questions/42833540/keyword-const-does-not-make-the-value-immutable-what-does-it-mean#answer-42833697) is a much better explanation on the topic. – Bryson Reynolds Mar 24 '18 at 09:19
  • Oh man, I'm so sorry, you need to name that function: `async function checkFiles () {}` – Bryson Reynolds Mar 24 '18 at 09:22
  • thanks alot , even the simplest things trows me off track. Ill try another test. – Frederik 84 Mar 24 '18 at 09:35
  • Ok so I just tested this, and I got no error msgs , however It did not find any files either.. The path is correct as far as I can tell ., here is the path copied from filezilla "/var/scraper/public/images/flags" – Frederik 84 Mar 24 '18 at 09:47