117

How can I tell in JavaScript what path separator is used in the OS where the script is running?

Pang
  • 9,564
  • 146
  • 81
  • 122
  • Why do you need this when Javascript is run inside the browser with complete OS isolation? You can't access files from your local computer... – lms Sep 24 '08 at 07:25
  • 1
    JavaScript is usually, but not always, run in the browser. Some examples of JavaScript uses outside the browser are Mozilla XULRunner apps, js scripts run using a command-line interpreter like V8 or WSH, and ASP pages written in JScript. There are many uses for JS. – Joel Anair Sep 24 '08 at 12:44
  • I'm sure you've already solved the issue, but I've added a use case for your question and an answer below, because like you, I know there's always a case where you can't depend on the OS to resolve the separator for you! :). Cheers! – Decoded Feb 06 '16 at 20:48
  • 2
    This question is very relevant because JavaScript is often run inside Node.js. There you can and want to access the file-system so the path-separator matters. This is also one of the pain-points if you want to create multi-OS Node.js applications. Node.js is multi-platform but that does not mean that any Node.js program runs on all supported OSes, without you paying special attention to the file-paths you use. – Panu Logic Aug 02 '18 at 15:59

6 Answers6

219

Use path module in node.js returns the platform-specific file separator.
example

path.sep  // on *nix evaluates to a string equal to "/"

Edit: As per Sebas's comment below, to use this, you need to add this at the top of your js file:

const path = require('path')
Michael Tontchev
  • 909
  • 8
  • 23
t98907
  • 2,287
  • 2
  • 13
  • 7
  • 3
    You could improve your answer [specifying how: `path.sep`](https://nodejs.org/docs/latest/api/path.html#path_path_sep). – Ionică Bizău Mar 08 '15 at 12:24
  • 13
    `const path = require('path');` – Sebas Jan 27 '17 at 11:52
  • Though I know I can use '/' in most if not all of my cases. When I print output to the console for feedback or logging. I like to use the same slashes in a full path. – b01 May 18 '18 at 21:40
  • I think above is the correct answer and also the simplest solution. As pointed out by Sebas to get access to the path-module you must do path = require('path'). If you're a Node.programmer, even novice, you probably already know that. – Panu Logic Aug 02 '18 at 15:51
29

Afair you can always use / as a path separator, even on Windows.

Quote from http://bytes.com/forum/thread23123.html:

So, the situation can be summed up rather simply:

  • All DOS services since DOS 2.0 and all Windows APIs accept either forward slash or backslash. Always have.

  • None of the standard command shells (CMD or COMMAND) will accept forward slashes. Even the "cd ./tmp" example given in a previous post fails.

VVS
  • 19,405
  • 5
  • 46
  • 65
  • 1
    JFYI: cmd.exe handles "cd /windows" (as an example) correctly on both Windows XP and Windows 7. – Eugene Mayevski 'Callback Jan 17 '11 at 11:49
  • 4
    This is not a fully CORRECT answer to the posed question... see "The Correct Answer" Below :). – Decoded Feb 06 '16 at 20:42
  • 9
    I downvoted this answer because it ignores the perfect validity of the question- namely that there are cases where you actually need to know the path separator being used. For instance, needing to split a path into pieces would use the separator. – MirroredFate Aug 24 '16 at 22:29
  • 3
    @VVS - Does not work in scenarios where you use both types of slashes (at least on Windows 7). Consider the case where you are constructing a variable using __dirname and then you need to append the rest of the path. For example: __dirname + '/images'. In that example __dirname will use the OS specific slashes, but if you try to use /images and you're on Windows, you will end up with a path like c:\somepath/images, and that won't work on Windows. I just ran into this case, which is why I mention it :). – dcp May 09 '17 at 14:17
  • 2
    VVS's answer is correct, with the exception of parsing a path given by a file input in internet explorer (tested with IE8 - I do not know about other versions). In this case, the path given by the input element's value (input.value) is in the form "C:\fakepath\<filename>". Note the backslashes here. – Milagre Aug 01 '10 at 03:49
  • Does not work consistently across browsers when accessing `input type="file"`, which now often reports `C:\fakepath` prefix. Thus, backslashes instead of foreslashes. So, if you were parsing that for instance to get basename using `split`, you wouldn't get what you wanted. – Volomike May 26 '22 at 03:24
16

The Correct Answer

Yes all OS's accept CD ../ or CD ..\ or CD .. regardless of how you pass in separators. But what about reading a path back. How would you know if its say, a 'windows' path, with ' ' and \ allowed.

The Obvious 'Duh!' Question

What happens when you depend on, for example, the installation directory %PROGRAM_FILES% (x86)\Notepad++. Take the following example.

var fs = require('fs');                             // file system module
var targetDir = 'C:\Program Files (x86)\Notepad++'; // target installer dir

// read all files in the directory
fs.readdir(targetDir, function(err, files) {

    if(!err){
        for(var i = 0; i < files.length; ++i){
            var currFile = files[i];

            console.log(currFile); 
            // ex output: 'C:\Program Files (x86)\Notepad++\notepad++.exe'

            // attempt to print the parent directory of currFile
            var fileDir = getDir(currFile);

            console.log(fileDir);  
            // output is empty string, ''...what!?
        }
    }
});

function getDir(filePath){
    if(filePath !== '' && filePath != null){

       // this will fail on Windows, and work on Others
       return filePath.substring(0, filePath.lastIndexOf('/') + 1);
    }
}

What happened!?

targetDir is being set to a substring between the indices 0, and 0 (indexOf('/') is -1 in C:\Program Files\Notepad\Notepad++.exe), resulting in the empty string.

The Solution...

This includes code from the following post: How do I determine the current operating system with Node.js

myGlobals = { isWin: false, isOsX:false, isNix:false };

Server side detection of OS.

// this var could likely a global or available to all parts of your app
if(/^win/.test(process.platform))     { myGlobals.isWin=true; }
else if(process.platform === 'darwin'){ myGlobals.isOsX=true; }
else if(process.platform === 'linux') { myGlobals.isNix=true; }

Browser side detection of OS

var appVer = navigator.appVersion;
if      (appVer.indexOf("Win")!=-1)   myGlobals.isWin = true;
else if (appVer.indexOf("Mac")!=-1)   myGlobals.isOsX = true;
else if (appVer.indexOf("X11")!=-1)   myGlobals.isNix = true;
else if (appVer.indexOf("Linux")!=-1) myGlobals.isNix = true;

Helper Function to get the separator

function getPathSeparator(){
    if(myGlobals.isWin){
        return '\\';
    }
    else if(myGlobals.isOsx  || myGlobals.isNix){
        return '/';
    }

    // default to *nix system.
    return '/';
}

// modifying our getDir method from above...

Helper function to get the parent directory (cross platform)

function getDir(filePath){
    if(filePath !== '' && filePath != null){
       // this will fail on Windows, and work on Others
       return filePath.substring(0, filePath.lastIndexOf(getPathSeparator()) + 1);
    }
}

getDir() must be intelligent enough to know which its looking for.

You can get even really slick and check for both if the user is inputting a path via command line, etc.

// in the body of getDir() ...
var sepIndex = filePath.lastIndexOf('/');
if(sepIndex == -1){
    sepIndex = filePath.lastIndexOf('\\');
}

// include the trailing separator
return filePath.substring(0, sepIndex+1);

You can also use 'path' module and path.sep as stated above, if you want to load a module to do this simple of a task. Personally, i think it sufficient to just check the information from the process that is already available to you.

var path = require('path');
var fileSep = path.sep;    // returns '\\' on windows, '/' on *nix

And Thats All Folks!

Community
  • 1
  • 1
Decoded
  • 1,057
  • 13
  • 17
  • 2
    I like that you presented logic for finding the separator to use, breaking it into manageable chunks. This is how a professional works as an engineer. **+1** for that. Also, considering the age of the question and the lack of a `NodeJS` tag - you've answered for both *server* and *client* side. Your answer does fully - and *actually* - answer the question. For node, I think the path module is fine because it will not impact generated bytecode performance and should not impact readability (a single import statement). You're the only answer to client-side, however. This should be the accepted. – Rik Nov 28 '20 at 17:15
9

As already answered here, you can find the OS specific path separator with path.sep to manually construct your path. But you can also let path.join do the job, which is my preferred solution when dealing with path constructions:

Example:

const path = require('path');

const directory = 'logs';
const file = 'data.json';

const path1 = `${directory}${path.sep}${file}`;
const path2 = path.join(directory, file);

console.log(path1); // Shows "logs\data.json" on Windows
console.log(path2); // Also shows "logs\data.json" on Windows
Matt
  • 116
  • 6
Benny Code
  • 51,456
  • 28
  • 233
  • 198
0

In javascript you can get this information from window.navigator.userAgent

-6

Just use "/", it works on all OS's as far as I know.

Vincent McNabb
  • 33,327
  • 7
  • 31
  • 53