關(guān)于Node.js的__dirname,__filename沃但,process.cwd()磁滚,./文件路徑的一些坑

起因

原文收錄在我的 GitHub博客 (https://github.com/jawil/blog) ,喜歡的可以關(guān)注最新動態(tài)宵晚,大家一起多交流學習垂攘,共同進步,以學習者的身份寫博客淤刃,記錄點滴晒他。

最近在學習Node.js里面的fs模塊,遇到了一個比較詭異的現(xiàn)象逸贾,踩到了坑陨仅,就是讀取當前目錄下的一個文件津滞,死活讀取不到,由于之前對于Node.js里面的path模塊也不太熟悉灼伤,也沒系統(tǒng)研究過触徐,所以今天就踩了這個坑,記錄踩坑的過程狐赡,防止以后踩坑和大家也踩坑撞鹉。

說一下當時的情形:


QQ20170510-181437

我納悶的很半天,我明明就是讀取當前目錄下的1.findLargest.js颖侄,為什么提示找不到這個文件鸟雏,運行了幾遍,死活找不到1.findLargest.js這個文件览祖。

后來才發(fā)現(xiàn)是因為運行這個文件不是從當前目錄運行了孝鹊,從圖中可以看出,當前的目錄是/Users/jawil/Desktop/nodejs/demo/ES6-lottery/syntax/nodejs穴墅,而我運行這個腳本的目錄是/Users/jawil/Desktop/nodejs/demo/ES6-lottery惶室;這就是問題的所在了。不過為什么運行腳本的位置也會影響這個路徑呢玄货,且往下看皇钞。

探索

計算機不會欺騙人,一切按照規(guī)則執(zhí)行松捉,說找不到這個文件夹界,那肯定就是真的找不到,至于為什么找不到隘世,那就是因為我們理解有偏差可柿,我最初理解的'./'是當前執(zhí)行js文件所在的文件夾的絕對路徑,然后Node.js的理解卻不是這樣的丙者,我們慢慢往下看复斥。

Node.js中的文件路徑大概有 __dirname, __filename, process.cwd(), ./ 或者 ../,前三個都是絕對路徑械媒,為了便于比較目锭,./../ 我們通過 path.resolve('./')來轉(zhuǎn)換為絕對路徑。

簡單說一下這幾個路徑的意思纷捞,:

__dirname:    獲得當前執(zhí)行文件所在目錄的完整目錄名
__filename:   獲得當前執(zhí)行文件的帶有完整絕對路徑的文件名
process.cwd():獲得當前執(zhí)行node命令時候的文件夾目錄名 
./:           文件所在目錄

先看一看我電腦當前的目錄結(jié)構(gòu):

syntax/
    -nodejs/
        -1.findLargest.js
        -2.path.js
        -3.fs.js
    -regs
        -regx.js
        -test.txt

在 path.js 里面我們寫這些代碼痢虹,看看輸出是什么:

const path = require('path')
console.log('__dirname:', __dirname)
console.log('__filename:', __filename)
console.log('process.cwd():', process.cwd())
console.log('./:', path.resolve('./'))

在當前目錄下也就是nodejs目錄運行 node path.js,我們看看輸出結(jié)果:

__dirname:     /Users/jawil/Desktop/nodejs/demo/ES6-lottery/syntax/nodejs
__filename:    /Users/jawil/Desktop/nodejs/demo/ES6-lottery/syntax/nodejs/2.path.js
process.cwd(): /Users/jawil/Desktop/nodejs/demo/ES6-lottery/syntax/nodejs
./:            /Users/jawil/Desktop/nodejs/demo/ES6-lottery/syntax/nodejs
QQ20170510-183712

然后在 項目根目錄ES6-lottery 目錄下運行 node syntax/nodejs/2.path.js主儡,我們再來看看輸出結(jié)果:

__dirname:     /Users/jawil/Desktop/nodejs/demo/ES6-lottery/syntax/nodejs
__filename:    /Users/jawil/Desktop/nodejs/demo/ES6-lottery/syntax/nodejs/2.path.js
process.cwd(): /Users/jawil/Desktop/nodejs/demo/ES6-lottery
./:            /Users/jawil/Desktop/nodejs/demo/ES6-lottery
QQ20170510-184943

答案顯而易見奖唯?我們可以通過上面的例子對比,暫時得出表面的結(jié)論:

  • __dirname: 總是返回被執(zhí)行的 js 所在文件夾的絕對路徑
  • __filename: 總是返回被執(zhí)行的 js 的絕對路徑
  • process.cwd(): 總是返回運行 node 命令時所在的文件夾的絕對路徑
  • ./: 跟 process.cwd() 一樣糜值,返回 node 命令時所在的文件夾的絕對路徑

但是丰捷,我們再來看看這個例子坯墨,我們在上面的例子加幾句代碼,然后:

我們在1.findLargest.js先加這句代碼

exports.A = 1;

再來在剛才報錯的3.fs.js里面加這兩句代碼看看:

const test = require('./1.findLargest.js');

console.log(test)

運行node syntax/nodejs/3.fs.js瓢阴,最后看看結(jié)果:

QQ20170510-185549

再次疑惑

為什么都是讀取./1.findLargest.js文件畅蹂,一樣的路徑,為什么require能獲取到荣恐,而readFile讀取不到呢?

于是查了不少資料累贤,看到了一些關(guān)于require引入模塊的機制叠穆,從中學到了不少,也明白了為什么是這樣臼膏。

我們先了解一下require() 的基本用法:

下面的內(nèi)容來自require() 源碼解讀,由阮一峰翻譯自《Node使用手冊》硼被。

QQ20170510-190528

我們從第(2)小條的a部分可以看出:

(2)如果 X 以 "./" 或者 "/" 或者 "../" 開頭 
  a. 根據(jù) X 所在的父模塊,確定 X 的絕對路徑渗磅。
  b. 將 X 當成文件嚷硫,依次查找下面文件,只要其中有一個存在始鱼,就返回該文件仔掸,不再繼續(xù)執(zhí)行。

const test = require('./1.findLargest.js')按照上面規(guī)則翻譯一遍就是:

  1. 根據(jù)1.findLargest.js所在的父模塊医清,確定1.findLargest.js的絕對路徑為/Users/jawil/Desktop/nodejs/demo/ES6-lottery/syntax/nodejs起暮,關(guān)于其中的尋找細節(jié)這里不做探討。

  2. 先把1.findLargest.js當成文件会烙,依次查找當前目錄下的1.findLargest.js负懦,找到了,就返回該文件柏腻,不再繼續(xù)執(zhí)行纸厉。

根據(jù)require的基本規(guī)則,對于上面出現(xiàn)的情形也就不足為奇了五嫂,更多require的機制和源碼解讀颗品,請移步:
require() 源碼解讀

那么關(guān)于 ./ 正確的結(jié)論是:
require() 中使用是跟 __dirname 的效果相同贫导,不會因為啟動腳本的目錄不一樣而改變抛猫,在其他情況下跟 process.cwd() 效果相同,是相對于啟動腳本所在目錄的路徑孩灯。

總結(jié):

  • __dirname: 獲得當前執(zhí)行文件所在目錄的完整目錄名
  • __filename: 獲得當前執(zhí)行文件的帶有完整絕對路徑的文件名
  • process.cwd():獲得當前執(zhí)行node命令時候的文件夾目錄名
  • ./: 不使用require時候闺金,./與process.cwd()一樣,使用require時候峰档,與__dirname一樣

只有在 require() 時才使用相對路徑(./, ../)的寫法败匹,其他地方一律使用絕對路徑寨昙,如下:


// 當前目錄下
 path.dirname(__filename) + '/path.js'; 
// 相鄰目錄下
 path.resolve(__dirname, '../regx/regx.js');

最后看看改過之后的結(jié)果,不會報錯找不到文件了掀亩,不管在哪里執(zhí)行這個腳本文件舔哪,都不會出錯了,防止以后踩坑槽棍。

QQ20170510-193604
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末捉蚤,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子炼七,更是在濱河造成了極大的恐慌缆巧,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件豌拙,死亡現(xiàn)場離奇詭異陕悬,居然都是意外死亡,警方通過查閱死者的電腦和手機按傅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門捉超,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人唯绍,你說我怎么就攤上這事拼岳。” “怎么了推捐?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵裂问,是天一觀的道長。 經(jīng)常有香客問我牛柒,道長堪簿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任皮壁,我火速辦了婚禮椭更,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蛾魄。我一直安慰自己虑瀑,他們只是感情好,可當我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布滴须。 她就那樣靜靜地躺著舌狗,像睡著了一般收壕。 火紅的嫁衣襯著肌膚如雪缭嫡。 梳的紋絲不亂的頭發(fā)上宪彩,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天主届,我揣著相機與錄音,去河邊找鬼君丁。 笑死,一個胖子當著我的面吹牛橡庞,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播毙死,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼喻鳄,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了确封?” 一聲冷哼從身側(cè)響起除呵,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎爪喘,沒想到半個月后颜曾,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡秉剑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年泛豪,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片侦鹏。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡诡曙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出略水,到底是詐尸還是另有隱情价卤,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布渊涝,位于F島的核電站慎璧,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏跨释。R本人自食惡果不足惜胸私,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鳖谈。 院中可真熱鬧岁疼,春花似錦、人聲如沸蚯姆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至疙驾,卻和暖如春凶伙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背它碎。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工函荣, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留傻挂,地道東北人。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓金拒,卻偏偏與公主長得像,于是被迫代替她去往敵國和親套腹。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 個人入門學習用筆記幢码、不過多作為參考依據(jù)。如有錯誤歡迎斧正 目錄 簡書好像不支持錨點尖飞、復制搜索(反正也是寫給我自己看...
    kirito_song閱讀 2,449評論 1 37
  • Node.js是目前非持⒏保火熱的技術(shù),但是它的誕生經(jīng)歷卻很奇特政基。 眾所周知贞铣,在Netscape設(shè)計出JavaScri...
    w_zhuan閱讀 3,607評論 2 41
  • 1 Node.js模塊的實現(xiàn)# 之前在網(wǎng)上查閱了許多介紹Node.js的文章,可惜對于Node.js的模塊機制大都...
    七寸知架構(gòu)閱讀 2,053評論 1 50
  • 1 Node.js模塊的實現(xiàn) 之前在網(wǎng)上查閱了許多介紹Node.js的文章,可惜對于Node.js的模塊機制大都著...
    zlx_2017閱讀 1,221評論 0 1
  • 這是一個發(fā)生在我身邊的真實案例痪寻,已經(jīng)過去半月有余芽唇,至今想來仍覺得汗毛直豎顾画,把孩子養(yǎng)大太不容易了,他們這一生遇到的各...
    職場媽媽閱讀 335評論 0 2