node.js 中的 __dirname 和 ./ 有啥区别?
Posted
技术标签:
【中文标题】node.js 中的 __dirname 和 ./ 有啥区别?【英文标题】:What is the difference between __dirname and ./ in node.js?node.js 中的 __dirname 和 ./ 有什么区别? 【发布时间】:2011-12-29 04:51:02 【问题描述】:在 Node.js 中编程并引用与当前目录相关的文件时,是否有任何理由使用 __dirname
变量而不是常规的 ./
?到目前为止,我一直在我的代码中使用 ./ 并且刚刚发现 __dirname
的存在,并且本质上想知道将我的 ./ 转换为它是否明智,如果是,为什么会这样一个聪明的主意。
【问题讨论】:
tl;dr:所以,基本上,区别在于'./'和'process.cwd()'指的是调用脚本的终端的当前目录,而'__dirname'指的是到存储脚本的目录。 除非在require
内部使用.
。 require
中的路径始终相对于包含对 require
的调用的文件。
【参考方案1】:
./
指的是当前工作目录,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/dir
并运行 node 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 是当前的工作目录...感谢您的澄清! 有什么办法可以用fs引用app的工作目录吗?例如,我正在尝试从工作目录/movies
加载文件,但由于我的模块位于文件/custom_modules/
中,__dirname
尝试从/custom_modules/movies
获取电影
您可以使用./
或process.cwd()
。见nodejs.org/api/process.html#process_process_cwd
值得注意的是,在 require 语句中使用 __dirname 而不是 ./ 不是一个好主意,因为尽管它们在节点中的行为相同,但它可能会导致 browserify 构建包的问题否则很容易避免。【参考方案2】:
要点
在 Node.js 中,__dirname
始终是当前执行脚本所在的目录 (see this)。因此,如果您在/d1/d2/myscript.js
中键入__dirname
,则值将是/d1/d2
。
相比之下,.
为您提供了在您使用 path
和 fs
等库时在终端窗口中运行 node
命令的目录(即您的工作目录)。从技术上讲,它最初是您的工作目录,但可以使用 process.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
中的路径总是相对于你调用它的文件。它与您的工作目录无关。
【讨论】:
IMO,这个解释比接受的答案更清楚一些(你知道,“当前目录”在那里有点模棱两可)。 我同意。我将更改接受的答案。请记住,这个答案是在原始答案被接受 2.5 年后添加的,而我现在才注意到它(又过了 2 年)。 :) 迟到总比没有好! 值得注意的是./
不是总是节点启动的目录。它以这种方式开始,但可以通过process.chdir()
进行更改。因此,./
始终是当前工作目录,通常是启动节点的目录,除非您的代码显式更改了工作目录。
我对 Using 有点困惑。在 require 部分,如果 require 中的路径总是相对于您正在调用的文件,那么路径不应该是 require('../thefile') 而不是 require('../dir1/thefile') 吗?我认为 .. 已经将路径的当前位置从 dir2 拉回到 dir1 一级。你还需要把 dir1 放在路径中还是我错过了什么?
如果您需要在某个脚本中使用../someDir
,并且您要从不同的文件夹运行该命令,您会怎么做?以上是关于node.js 中的 __dirname 和 ./ 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章