当前位置:首页 > 知识

nodejs命令行切换到指定目录

用Node.js写脚本,命令目录十有八九得跟文件系统打交道。行切而一旦涉及文件读写,指定第一件事就是命令目录确认当前工作目录在哪。很多人以为`process.cwd()`拿到的行切就是脚本文件所在目录,结果一跑就报错——文件找不到。指定问题出在哪儿?命令目录命令行启动时的目录,和脚本文件的行切位置,压根不是指定一回事。

比如你在`/Users/you/projects`下执行`node scripts/build.js`,命令目录脚本里写`fs.readFileSync('./config.json')`,行切Node.js会去`/Users/you/projects/config.json`找,指定而不是命令目录`/Users/you/projects/scripts/config.json`。这个坑我踩过不止一次。行切后来学乖了,指定要么用`__dirname`拼绝对路径,要么在脚本开头就主动切换工作目录。

process.chdir():直接但有限制

Node.js提供了一个原生方法:process.chdir(directory)。传一个路径进去,当前进程的工作目录就变了。后续所有相对路径操作,都基于新目录解析。

const path = require('path'); // 切换到脚本所在目录 process.chdir(__dirname); console.log('当前目录:', process.cwd()); // 输出: /Users/you/projects/scripts

这行代码放在脚本顶部,后面所有`./xxx`的路径引用就都对了。简单粗暴,效果立竿见影。

但有个细节得注意:`process.chdir()`切换的是整个进程的目录,不是某个模块的。如果脚本里引入了其他第三方模块,它们内部的相对路径操作也会受影响。绝大多数情况下这没问题,可要是某个依赖库假设了特定的工作目录,就可能出幺蛾子。我遇到过一次,某个日志库默认往`./logs`写文件,切换目录后日志跑到了脚本目录下,排查了半天。

路径拼接比切换目录更稳妥

说实话,我现在越来越少用`process.chdir()`了。更常见的做法是用`path.resolve()`或`path.join()`拼出绝对路径,直接传给`fs`方法。

const fs = require('fs'); const path = require('path'); const configPath = path.resolve(__dirname, 'config.json'); const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));

这样写不依赖当前工作目录,脚本从哪儿启动都行。`__dirname`永远指向脚本文件所在目录,`path.resolve()`把它和相对路径拼成绝对路径。干净、明确、没有副作用。

两种方式各有利弊。`process.chdir()`适合那种整个脚本都围绕某个目录操作的场景,比如构建工具、脚手架。路径拼接则更适合库代码和工具函数,不污染全局状态。

一个实际案例

之前写过一个批量重命名图片的脚本,放在`tools/rename/`目录下,图片在`assets/photos/`。最初图省事,直接写`fs.readdirSync('./assets/photos')`,在项目根目录跑没问题。后来同事在`tools/rename/`目录下直接执行`node index.js`,立刻报错——找不到`./assets/photos`。

改成这样就好了:

const projectRoot = path.resolve(__dirname, '../../'); const photoDir = path.join(projectRoot, 'assets', 'photos'); process.chdir(projectRoot); // 或者直接用 photoDir 做绝对路径操作

核心思路就一句话:别让脚本的运行结果取决于你在哪个目录敲的`node`命令。要么主动切过去,要么用绝对路径绕开这个变量。

几个容易忽略的点

Windows和Unix的路径分隔符不同,`path.join()`会自动处理,手动拼字符串就容易翻车。另外,`process.chdir()`在切换前最好确认目标目录存在,否则直接抛异常。用`fs.existsSync()`检查一下,或者用`try/catch`兜底。

还有,ESM模块里没有`__dirname`,得用`import.meta.url`配合`fileURLToPath`来获取当前文件路径。这个转换写起来略啰嗦,但习惯了也就那样。

命令行切目录这事,说大不大,说小不小。写脚本时多花三十秒想清楚路径问题,能省下后面半小时的调试时间。

分享到: