node.js中的__dirname和./有什么区别?


497

在Node.js中编程并引用与当前目录相关的文件时,是否有任何理由使用__dirname变量而不是常规变量./?到目前为止,我一直在代码中使用./,只是发现了。的存在__dirname,并且本质上是想知道将./转换为该代码是否明智,如果是的话,那为什么会是一个明智的主意。


47
tl; dr:所以,基本上,不同之处在于'./'和'process.cwd()'指向调用脚本的终端的当前目录,而'__dirname'则指向脚本所在的目录存储。
Gui Imamura

1
除了何时.在内部使用require。内部路径require始终相对于包含对的调用的文件require
Govind Rai

Answers:


813

要点

在Node.js中,__dirname始终是当前正在执行的脚本所在的目录(请参阅参考资料)。所以,如果你键入__dirname/d1/d2/myscript.js,该值会/d1/d2

相比之下,使用诸如和的库时,会在终端窗口中.为您提供从中运行node命令的目录(即工作目录)。从技术上讲,它从您的工作目录开始,但是可以使用进行更改。pathfsprocess.chdir()

例外是.与一起使用时require()。内部路径require始终相对于包含对的调用的文件require

例如...

假设您的目录结构是

/dir1
  /dir2
    pathtest.js

pathtest.js包含

var path = require("path");
console.log(". = %s", path.resolve("."));
console.log("__dirname = %s", path.resolve(__dirname));

你也是

cd /dir1/dir2
node pathtest.js

你得到

. = /dir1/dir2
__dirname = /dir1/dir2

您的工作目录就是/dir1/dir2这样.。由于pathtest.js位于/dir1/dir2那,所以__dirname也要解决。

但是,如果您从以下位置运行脚本 /dir1

cd /dir1
node dir2/pathtest.js

你得到

. = /dir1
__dirname = /dir1/dir2

在那种情况下,您的工作目录就是/dir1这样,所以可以.解决,但__dirname仍然可以解决/dir1/dir2

.在内部使用require...

如果里面dir2/pathtest.js你有一个require电话到包括文件里面dir1,你会一直

require('../thefile')

因为里面的路径require总是相对于您要在其中调用的文件的。它与您的工作目录无关。


38
IMO,这一解释比接受的答案中的解释更清楚(您知道,“当前目录”在那里有点模棱两可)。
化身为2013年

5
我同意。我将更改接受的答案。请记住,此答案是在原始答案被接受2.5年后添加的,而我只是现在才注意到(又是2年后)。:) 迟到总比不到好!
thisissami 2015年

14
值得注意的是,./并非总是从中启动节点的目录。它以这种方式开始,但是可以通过更改process.chdir()。因此,./始终是当前的工作目录,通常是从其启动目录节点,除非您的代码显式更改了工作目录。
gilly3 2015年

3
我对Using有点困惑。在require内,如果require内的路径始终是相对于您要调用的文件,不是该路径应该是require('../ thefile')而不是require('../ dir1 / thefile')吗?我以为..已经将路径的当前位置从dir2返回到dir1了。您是否仍然需要将dir1放在路径中,还是我想念一些理解的东西?
andromada

1
如果需要../someDir在某些脚本中使用并且要从其他文件夹运行命令,该怎么办?
cbdeveloper

154

./引用当前工作目录,但require()函数中除外。使用时require(),它将转换./为当前文件的目录。__dirname始终是当前文件的目录。

例如,具有以下文件结构

/home/user/dir/files/config.json

{
  "hello": "world"
}

/home/user/dir/files/somefile.txt

text file

/home/user/dir/dir.js

var fs = require('fs');

console.log(require('./files/config.json'));
console.log(fs.readFileSync('./files/somefile.txt', 'utf8'));

如果我跑cd进去/home/user/dirnode dir.js我会得到

{ hello: 'world' }
text file

但是,当我从运行相同的脚本/home/user/,我得到

{ hello: 'world' }

Error: ENOENT, no such file or directory './files/somefile.txt'
    at Object.openSync (fs.js:228:18)
    at Object.readFileSync (fs.js:119:15)
    at Object.<anonymous> (/home/user/dir/dir.js:4:16)
    at Module._compile (module.js:432:26)
    at Object..js (module.js:450:10)
    at Module.load (module.js:351:31)
    at Function._load (module.js:310:12)
    at Array.0 (module.js:470:10)
    at EventEmitter._tickCallback (node.js:192:40)

使用./与工作require,但不适合fs.readFileSync。这是因为fs.readFileSync./会转化为CWD(在这种情况下/home/user/)。并且/home/user/files/somefile.txt不存在。


哦,我认为__dirname是当前的工作目录...感谢您的澄清!
thisissami

有什么方法可以使用fs引用应用程序的工作目录?例如,我正在尝试从工作目录中加载文件/movies,但是由于我的模块在文件中/custom_modules/,因此__dirname尝试从中抓取影片/custom_modules/movies

2
您可以使用./process.cwd()。参见nodejs.org/api/process.html#process_process_cwd
2014年

值得注意的是,在require语句中在./上使用__dirname 并不是一个好主意,因为尽管它们在节点中的行为相同,但它可能导致浏览器的构建问题,而这些问题很容易避免。
杰德·沃森
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.