6

Running a node app to read a directory

fs.readdirSync('‎/Users/edwardthompson/Dropbox/Apps/EvidentiaSoftware/records/thompson-hayward');

I consistently get

 Stack:
    error properties: Object({ errno: -2, syscall: 'scandir', code: 'ENOENT', path: '‎/Users/edwardthompson/Dropbox/Apps/EvidentiaSoftware/records/thompson-hayward' })
    Error: ENOENT: no such file or directory, scandir '‎/Users/edwardthompson/Dropbox/Apps/EvidentiaSoftware/records/thompson-hayward'

But I know the directory is there

ls -al /Users/edwardthompson/Dropbox/Apps/EvidentiaSoftware/records/thompson-hayward
    total 0
    drwxr-xr-x@ 9 edwardthompson  staff  288 Jan 18  2019 .
    drwxr-xr-x@ 6 edwardthompson  staff  192 Aug 29 12:30 ..
    drwxr-xr-x@ 9 edwardthompson  staff  288 Jan 18  2019 Births
    drwxr-xr-x@ 4 edwardthompson  staff  128 Jan 18  2019 Census
    drwxr-xr-x@ 3 edwardthompson  staff   96 Jan 18  2019 Deaths
    drwxr-xr-x@ 7 edwardthompson  staff  224 Jan 18  2019 Marriages
    drwxr-xr-x@ 4 edwardthompson  staff  128 Jan 18  2019 Military
    drwxr-xr-x@ 3 edwardthompson  staff   96 Jan 18  2019 Other
    drwxr-xr-x@ 8 edwardthompson  staff  256 Jan 18  2019 books

Not sure how to proceed

fs.lstat gives me the same ENOENT results. The Dropbox directory has extended attributes (can't find getfattr)

I tried /user/... and it did not make a difference

ed4becky
  • 1,488
  • 1
  • 17
  • 54
  • maybe a permissions issue with access to the `/Users/edwardthompson/` directory. is your node environment running with the same user, or one with the proper group to have access? – Derek Aug 31 '19 at 01:38
  • Maybe try adding the harddrive letter to the path like `C:/...` – MauriceNino Aug 31 '19 at 01:40
  • 2
    FYI the path in the stack output starts with `/User/` and in your function call and `ls` call it starts with `/Users`/ – Derek Aug 31 '19 at 01:41
  • 1
    /User/ was a copy paste error on my part (I was trying something). C:/ has no meaning on a linux or macos file system. I keep trying to see if its permissions somehow, but I am running as myself and I can do it – ed4becky Aug 31 '19 at 01:45
  • Does node fs.readdir have issues with extended attributes (xattr)? – ed4becky Aug 31 '19 at 01:45
  • If you intend for the path to start with be `/Users/`, then please edit your question to show the correct code and errors. Otherwise, we're chasing ghosts. – jfriend00 Aug 31 '19 at 02:07
  • @ed4becky Have you tried having the node application read from a different location? You could also try `getfattr` on the directory and see what the output is. – Mordred Sep 08 '19 at 18:39
  • I've seen this error when the path was symlinked (or maybe a subpath of the path is a symlink?). This also happens on older MacOS because the home folder was lowercase (while displayed as `/Users/`). did you try `lstat`? – ben Sep 09 '19 at 13:33
  • see results of your recommendations in edited version. Basically, no change... This particular directory does not have a symlink – ed4becky Sep 09 '19 at 18:51
  • I think it might have something to do with the extended attributes of that directory. Can you add the result of `xattr`. – Josnidhin Sep 10 '19 at 02:00
  • Found the issue but I don't understand it. let p = '\/Users/edwardthompson/Dropbox/Apps/EvidentiaSoftware/records/thompson-hayward'; removes a hidden? character that is inserted before the path, but if I just do let p = '/Users/edwardthompson/Dropbox/Apps/EvidentiaSoftware/records/thompson-hayward'; a hidden character gets inserted as the first character, corrupting the path. Why would I have to escape the first forward slash? – ed4becky Sep 11 '19 at 01:42
  • @ed4becky did you copy paste the path from somewhere or type it manually? Does re-typing the path manually help with that hidden char? – exside Sep 11 '19 at 16:13
  • @exside I tried both – ed4becky Sep 12 '19 at 18:37
  • Are any of the directories in the path symlinks if so node needs to be told to follow symlinks? – Barkermn01 Sep 12 '19 at 23:34
  • Does this also happen when Dropbox is not running? – htho Sep 13 '19 at 09:14

5 Answers5

5
const path = require('path');

const dirName = path.join(__dirname, '‎/ (../)x? /records/thompson-hayward');

(../)x? replace this with ../ how many times you need

fs.readdirSync(dirName).forEach(folder => {
// code here
});
Fiodorov Andrei
  • 1,778
  • 1
  • 11
  • 26
  • path.join gave me : /Users/edwardthompson/IdeaProjects/evidentia4/src/app/services/‎/Users/edwardthompson/Dropbox/Apps/EvidentiaSoftware/records/thompson-hayward, which of course is wrong, BUT it revealed some hidden character between the two paths. I noticed that the error message I usually get has a space befor ethe base of the path - this one did not. – ed4becky Sep 11 '19 at 01:36
  • ths ../ approach won't work for my app - the directory is hardcoded now but will be based on user selection. – ed4becky Sep 12 '19 at 12:04
2

You could try using path.resolve():

fs.readdirSync(path.resolve(‘Users’, ‘edwardthompson’, ‘Dropbox’, ‘Apps’, ‘EvidentiaSoftware’, ‘records’, ‘thompson-hayward’));

b3nThomas
  • 47
  • 6
  • oddly, the path resolve gave me /Users/edwardthompson/IdeaProjects/evidentia4/Users/edwardthompson/Dropbox/Apps/EvidentiaSoftware/records/thompson-hayward – ed4becky Sep 11 '19 at 01:32
2

"/Users/edwardthompson/Dropbox/Apps/EvidentiaSoftware/records/thompson-hayward" is not the correct path – this path starts with / which is the root directory.

With Linux the ./ is a shortcut to the current directory.

Try Something like this "./Users/edwardthompson/Dropbox/Apps/EvidentiaSoftware/records/thompson-hayward"

here is a link to a working example showing a similar error if you omit the . https://repl.it/@joshuaaguilar20/FrequentFunctionalFraction

      var fs = require('fs');

fs.writeFile('./newFile.txt', 'Hello World', function(error){
  if(error){
    throw error;
  } else {
    console.log('success');
  }
});

/* let wrong = fs.readdirSync("/newDir", function (err) {
  console.log(err)
}) */

/* 
Returns Error 
Error: ENOENT: no such file or directory, scandir '/newDir'
    at Object.readdirSync (fs.js:790:3)
    at evalmachine.<anonymous>:11:12
    at Script.runInContext (vm.js:133:20)
    at Object.runInContext (vm.js:311:6)
    at evaluate (/run_dir/repl.js:133:14)
    at ReadStream.<anonymous> (/run_dir/repl.js:116:5)
    at ReadStream.emit (events.js:198:13)
    at addChunk (_stream_readable.js:288:12)
    at readableAddChunk (_stream_readable.js:269:11)
    at ReadStream.Readable.push (_stream_readable.js:224:10)

 */


//Correct 

let x = fs.readdirSync("./newDir", function (err) {
  //adding ./ allows unix to find the Dir 
  console.log(err)
})

console.log(x)
Josh
  • 1,059
  • 10
  • 17
1

A simple way to debug would be to try reading a different dir located in /Users/{username}. If it works, you might want to look into symlink issues with readdir. It is likely that Dropbox creates a symlink that is not properly resolved.

You can use fs.realpath() or fs.realpathSync to obtain the realpath of the dir you're looking for, and then use readdir on the realpath instead.

BPS Julien
  • 126
  • 2
  • this worked for me thank you so much! readdirSync worked locally on my Mac, but in a docker container that uses Ubuntu it failed. So i had to use realpathSync('/some/path') like you suggested and pass the result of that into fs.readdirSync – drussell Oct 30 '20 at 22:21
0

You can do some diagnostic work on the path with the hidden character and perhaps learn something about what it is.

If this creates the problem path:

let p = '/Users/edwardthompson/Dropbox/Apps/EvidentiaSoftware/records/thompson-hayward';

Then, you can do this to see what that first character is:

 console.log(p.charCodeAt(0));

Or, output all the char codes in the string:

console.log(p.split("").map(chr => chr.charCodeAt(0).toString()).join(","));

Here it is in a runnable snippet (which does not reproduce your problem on my computer, but might show something on yours):

let p = '/Users/edwardthompson/Dropbox/Apps/EvidentiaSoftware/records/thompson-hayward';
let charCodes = p.split("").map(chr => chr.charCodeAt(0));
let str = charCodes.map((code, index) => {
    return `<tr><td>${p.charAt(index)}</td><td>${code.toString()}</td><td> 0x${code.toString(16)}</td></tr>`
}).join("");
document.write(`<style>table.colright td:nth-child(2), table.colright th:nth-child(2), table.colright td:nth-child(3), table.colright th:nth-child(3) {
  text-align: right;
}</style>`);
document.write("<table class='colright'>")
document.write("<thead><tr><th>&nbsp;char<br>&nbsp;</th><th>&nbsp;decimal<br>value</th><th>hex<br>&nbsp;&nbsp;&nbsp;&nbsp;value</th></tr></thead>");    
document.write("<tbody>");
document.write(str);
document.write("</tbody></table>");

My only working theory (which is an unsubstantiated guess) is that somehow the /U that starts the string is being interpreted as the beginning of a manually specified unicode character on your system only. It's supposed to be \u as the unicode prefix, not /U, but it's certainly acting like somehow it is misinterpreting the /U.


FYI, you might also want to do this:

console.log(path.sep) 

just to make sure your path separator isn't somehow haywire for your platform.

jfriend00
  • 683,504
  • 96
  • 985
  • 979