花拾录
← 返回知识库

Git Bash 的 /tmp 和 Windows Python 的 /tmp 根本不是同一个目录

软件工程 / 工具导入2026/09/220 阅读0 评论

你用 curl 从 Git Bash 里下了个文件到 /tmp/x,命令回显一切正常。紧接着用 Windows 版的 Python 去读 /tmp/x,报「文件不存在」。你回去看 /tmp 目录,文件明明在那儿。两个程序对同一个路径,看到的是两个完全不同的地方。

现象

  • Git Bash 里 curl -o /tmp/x ... 成功,ls /tmp/x 也能看到文件;
  • 同一个 x,交给 Windows 原生程序(比如 python.exe)打开 /tmp/x,报 FileNotFoundError;
  • 甚至 ls 能列出 /tmp/x,但 Python 的 open('/tmp/x') 找不到。

看起来是「同一个路径」,实际是两个不同的物理位置。

根因

因为在 Git Bash 里,/tmp 不是一个真实的目录,而是一个虚拟映射。

MSYS(Git Bash 的底层)为了模拟 Unix 环境,会拦下对 /、/tmp、/home 这类 Unix 风格路径的访问,把它们重定向到 Windows 上的某个真实目录。比如 Git Bash 的 /tmp 往往对应 Windows 临时目录下的某个子目录,/home/<用户> 对应 Git 安装目录下的某个位置。

但关键在于:这个重定向只发生在 MSYS 自己的程序里。 当 Git Bash 启动一个 Windows 原生程序(python.exe、node.exe、各种 .exe)时,这个进程完全不认识 MSYS 的虚拟路径。它对 /tmp/x 的理解是字面意思——「当前盘符根目录下的 tmp 子目录里的 x」,也就是 C:\tmp\x 或 D:\tmp\x。

于是:

  • Git Bash 的 curl 把文件写进了「MSYS 的 /tmp」(真实位置是某个 Windows 临时目录);
  • Windows 的 Python 去读「字面的 /tmp」(真实位置是 C:\tmp)。

两个路径长得一样,指向的目录却不同,文件自然找不到。

同样的道理,MSYS 之外的很多东西都可能不一致:/ 的根、/home、/usr 都是这种虚拟映射。

解决

跨「环境」传文件时,只信显式绝对路径。

不要用 /tmp 这种在两套体系里含义不同的路径做中转。改成用一个明确的 Windows 绝对路径:

# 先在 Git Bash 里下载到显式的 Windows 路径
curl -o 'D:/tools/_upload/x' https://example.com/file

# 再用 Python 读同一个显式路径
python -c "open(r'D:\tools\_upload\x', 'rb').read()"

两边都用 D:\tools\_upload\ 这个物理上唯一的位置,就不会有歧义。

如果你确实需要知道 Git Bash 的 /tmp 到底映射到了哪里,可以用:

cd /tmp && pwd -W

pwd -W 会打印当前目录的 Windows 形式路径,你就能看到它的真实位置。

延伸与预防

这条坑的本质是:「路径字符串」不等于「文件位置」。 同一个字符串,在不同程序、不同环境里,可能被解释到不同的地方。

要判断一个路径会不会「变脸」,看两点:

  1. 谁来解释它。 是 MSYS 的程序,还是 Windows 原生程序?前者有虚拟映射,后者没有。
  2. 它是虚拟路径还是物理路径。 /tmp、/home、/ 这类是 Unix 惯例,在 Windows 上多半是虚拟的;C:\...、D:\... 是物理路径,处处一致。

所以一条可靠的实践:跨工具、跨语言、跨环境传文件时,统一用物理绝对路径做中转点,并把它当作双方约定好的「交换区」。 这个交换区可以是固定的一个目录,两边都按它来读写,中间不管经过多少层外壳,指向的都是同一个地方。

这跟前一条「MSYS 路径转换」是一个家族的问题——都是「你以为你写了个路径,其实是环境中某个中间层在替你解释它」。区别只在于:一条是改写,一条是重定向。

一个实用的排查习惯:当你怀疑「两个程序看到的路径不一样」时,让它们分别把「自己理解到的路径」打印出来。比如在 Git Bash 里 echo $PWD 和在 Python 里 print(os.getcwd()),同一时刻对比一下,往往一眼就能看出它们站在不同的根上。别在脑子里推演路径映射,直接让程序把答案打出来。

评论(0)

  • 还没有评论,来抢沙发~

相关文章