Jak określić separator ścieżki systemu operacyjnego w JavaScript?

82

Jak mogę sprawdzić w JavaScript, który separator ścieżki jest używany w systemie operacyjnym, w którym skrypt jest uruchomiony?

Ostry ból
źródło
Dlaczego jest to potrzebne, gdy JavaScript jest uruchamiany w przeglądarce z pełną izolacją systemu operacyjnego? Nie możesz uzyskać dostępu do plików z lokalnego komputera ...
lms,
JavaScript jest zazwyczaj uruchamiany w przeglądarce, ale nie zawsze. Niektóre przykłady zastosowań JavaScript poza przeglądarką to aplikacje Mozilla XULRunner, skrypty js uruchamiane przy użyciu interpretera wiersza poleceń, takiego jak V8 lub WSH, oraz strony ASP napisane w języku JScript. JS ma wiele zastosowań.
Joel Anair,
Jestem pewien, że rozwiązałeś już problem, ale dodałem przykład użycia dla twojego pytania i odpowiedź poniżej, ponieważ tak jak ty, wiem, że zawsze jest przypadek, w którym nie możesz polegać na systemie operacyjnym, aby rozwiązać problem separator dla Ciebie! :). Twoje zdrowie!
Odkodowano
2
To pytanie jest bardzo istotne, ponieważ JavaScript jest często uruchamiany w Node.js. Tam możesz i chcesz uzyskać dostęp do systemu plików, więc separator ścieżki ma znaczenie. Jest to również jeden z problemów, jeśli chcesz tworzyć aplikacje Node.js. dla wielu systemów operacyjnych. Node.js jest wieloplatformowy, ale nie oznacza to, że jakikolwiek program Node.js działa we wszystkich obsługiwanych systemach operacyjnych, bez zwracania szczególnej uwagi na używane ścieżki plików.
Panu Logic

Odpowiedzi:

20

Tak, zawsze możesz użyć / jako separatora ścieżki, nawet w systemie Windows.

Cytat z http://bytes.com/forum/thread23123.html :

Sytuację można więc podsumować dość prosto:

  • Wszystkie usługi DOS od DOS 2.0 i wszystkie interfejsy API Windows akceptują ukośnik lub lewy ukośnik. Zawsze ma.

  • Żadna ze standardowych powłok poleceń (CMD lub COMMAND) nie akceptuje ukośników. Nawet przykład „cd ./tmp” podany w poprzednim poście zawodzi.

VVS
źródło
1
Odpowiedź VVS jest poprawna, z wyjątkiem parsowania ścieżki podanej przez wejście pliku w przeglądarce Internet Explorer (testowane z IE8 - nie wiem o innych wersjach). W tym przypadku ścieżka podana przez wartość elementu wejściowego (input.value) ma postać „C: \ fakepath \ & lt; filename & gt;”. Zwróć uwagę na odwrotne ukośniki tutaj.
Milagre
JFYI: cmd.exe poprawnie obsługuje pliki „cd / windows” (jako przykład) zarówno w systemie Windows XP, jak i Windows 7.
Eugene Mayevski 'Callback
2
To nie jest w pełni PRAWIDŁOWA odpowiedź na postawione pytanie ... patrz „Poprawna odpowiedź” poniżej :).
Odkodowano
5
Głosowałem negatywnie na tę odpowiedź, ponieważ ignoruje ona idealną zasadność pytania - mianowicie, że istnieją przypadki, w których faktycznie musisz znać używany separator ścieżki. Na przykład konieczność podzielenia ścieżki na części spowoduje użycie separatora.
MirroredFate
2
@VVS - nie działa w scenariuszach, w których używasz obu typów ukośników (przynajmniej w systemie Windows 7). Rozważ przypadek, w którym konstruujesz zmienną przy użyciu __dirname, a następnie musisz dołączyć resztę ścieżki. Na przykład: __dirname + „/ images”. W tym przykładzie __dirname użyje ukośników specyficznych dla systemu operacyjnego, ale jeśli spróbujesz użyć / images i jesteś w systemie Windows, otrzymasz ścieżkę taką jak c: \ somepath / images, a to nie będzie działać w systemie Windows. Właśnie wpadłem na tę sprawę, dlatego o niej wspominam :).
dcp
160

Użyj pathmodułu w node.jszwraca separator plików specyficzny dla platformy.
przykład

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

Edycja: zgodnie z komentarzem Sebasa poniżej, aby z tego skorzystać, musisz dodać to na górze pliku js:

const path = require('path')
t98907
źródło
2
Można poprawić swoją odpowiedź podając jak:path.sep .
Ionică Bizău
11
const path = require('path');
Sebas
Chociaż wiem, że mogę używać znaku „/” w większości, jeśli nie we wszystkich przypadkach. Kiedy drukuję dane wyjściowe do konsoli w celu uzyskania opinii lub logowania. Lubię używać tych samych ukośników na całej ścieżce.
b01
Myślę, że powyżej jest prawidłowa odpowiedź, a także najprostsze rozwiązanie. Jak wskazał Sebas, aby uzyskać dostęp do modułu ścieżki, musisz wykonać path = require ('path'). Jeśli jesteś programistą Node., a nawet nowicjuszem, prawdopodobnie już to wiesz.
Panu Logic
7

Poprawna odpowiedź

Tak, wszystkie systemy operacyjne akceptują CD ../ lub CD .. \ lub CD .. niezależnie od tego, jak przekazujesz separatory. Ale co z odczytaniem ścieżki wstecz. Skąd możesz wiedzieć, czy to, powiedzmy, ścieżka „okna” z ' 'i \dozwolona.

Oczywiste „Duh!” Pytanie

Co się dzieje, gdy polegasz na przykład na katalogu instalacyjnym %PROGRAM_FILES% (x86)\Notepad++. Weźmy następujący przykład.

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);
    }
}

Co się stało!?

targetDirjest ustawiana na podłańcuch między indeksami 0i 0( indexOf('/')jest -1w C:\Program Files\Notepad\Notepad++.exe), co skutkuje pustym ciągiem.

Rozwiązanie...

Obejmuje to kod z następującego wpisu: Jak określić bieżący system operacyjny za pomocą Node.js.

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

Wykrywanie systemu operacyjnego po stronie serwera.

// 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; }

Wykrywanie systemu operacyjnego po stronie przeglądarki

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;

Funkcja pomocnicza, aby uzyskać 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...

Funkcja pomocnicza, aby uzyskać katalog nadrzędny (między platformami)

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() musi być wystarczająco inteligentny, aby wiedzieć, czego szuka.

Możesz uzyskać nawet naprawdę sprytny i sprawdzić oba, czy użytkownik wprowadza ścieżkę za pomocą wiersza poleceń itp.

// 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);

Możesz także użyć „path” module i path.sep, jak wspomniano powyżej, jeśli chcesz załadować moduł, aby wykonać to proste zadanie. Osobiście uważam, że wystarczy po prostu sprawdzić informacje z procesu, które są już dostępne.

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

I to wszystko!

Odszyfrowano
źródło
1
Podoba mi się, że przedstawiłeś logikę znajdowania separatora do użycia, dzieląc go na łatwe do zarządzania kawałki. Tak pracuje profesjonalista jako inżynier. +1 za to. Biorąc pod uwagę wiek pytania i brak NodeJStagu - odpowiedziałeś zarówno po stronie serwera, jak i klienta . Twoja odpowiedź w pełni - i faktycznie - odpowiada na pytanie. W przypadku węzła myślę, że moduł ścieżki jest w porządku, ponieważ nie wpłynie to na wydajność generowanego kodu bajtowego i nie powinno wpływać na czytelność (pojedyncza instrukcja importu). Jednak jesteś jedyną odpowiedzią po stronie klienta. To powinno być zaakceptowane.
Rik
1

Jak już tutaj odpowiedziałem, możesz znaleźć separator ścieżki specyficzny dla systemu operacyjnego, path.joinaby ręcznie utworzyć ścieżkę. Ale możesz też pozwolić path.joinsobie na to, co jest moim preferowanym rozwiązaniem przy konstrukcjach ścieżek:

Przykład:

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
Benny Neugebauer
źródło
-3

Po prostu użyj "/", to działa na wszystkich systemach operacyjnych, o ile wiem.

Vincent McNabb
źródło
4
OP zapytał, jak to zrobić determine, a nie jaki operator działa wszędzie :-)
Steel Brain
3
Działa, gdy musisz przeanalizować ścieżkę, aby coś wyodrębnić.
Chris Seufert