【问题标题】:Python os.path.isdir returns true for dotsPython os.path.isdir 对点返回 true
【发布时间】:2018-03-18 10:28:56
【问题描述】:

我正在用 python 编写自己的 shell。现在我正在尝试在我的 shell 中实现 cd 命令。

执行这个命令的函数有几个变量:

self.current_dir = "C:\\" - 默认值,它的变化取决于用户使用 cd 命令的输入

dir = "..." - 用户键入的请求目录。 “...”是导致问题的输入示例。

这是我的代码:

def command_cd(self, dir):
    if os.path.isdir(self.shell.current_dir + dir):
        self.shell.current_dir = self.shell.current_dir + dir + "\\"

问题在于,由于某些奇怪的原因,os.path.isdir(self.shell.current_dir + dir) 在用户键入点时返回True(就像我上面给出的变量示例输入一样)。

即使你改变点的数量(甚至超过 5 个点)也会出现问题,我真的不知道是什么原因造成的。

显然没有名为 ... 或类似名称的文件夹。

如果我的问题不够清楚,请发表评论,我会修改它

【问题讨论】:

  • . 指向当前目录,.. 指向父目录。
  • @wim 哦,好的。你知道当我放 3 个点或 4 个点时它指的是什么吗?你认为它只是混淆了他们两个?
  • 我不使用 Windows,所以无法回答。这可能是一个错误,Python 的某些部分在 Windows 上没有得到很好的维护。
  • os.path.isdir("...") 在 POSIX 机器上返回 False,当显式导入 ntpathntpath.isdir("...") 也是如此。

标签: python windows shell os.path


【解决方案1】:

. 是当前目录,.. 是父目录,并且没有任何大于两个点的引用。

但是,os.path.isdir() 返回 True 的原因是因为 python 将大于两个点的所有内容注册为一个点。

import os

print(os.path.abspath(".......") == os.path.abspath("."))
print(os.path.abspath("....") == os.path.abspath("."))

# and that
print(os.path.samefile('......', '.'))
# also prints True

它们都将打印 True,因为 ............ 指向同一个地方。


正如 chepner 在 cmets 中指出的那样,这个问题在 POSIX 系统中不会发生,而它是由 os.stat 错误地将 '....' 等同于 '.' 引起的(事实并非如此,请参阅后面的编辑)


重要修改:

eriksun 评论:

Windows os.path.isdir是通过调用GetFileAttributes实现的, 调用NtQueryAttributesFile。像所有文件系统函数一样, 首先它必须将DOS 路径转换为原生NT 路径。到 内核"."".." 只是普通名称,所以运行时库 首先必须通过函数规范化路径 RtlGetFullPathName_Ustr,也被 os.path.abspath 使用,所以 结果是相似的。它减少两个以上点的方式和 最后一个组件中的尾随空格是继承自 DOS 的遗留物。 它正在尽最大努力模仿 1980 年代的 OS

因此这个问题与 python 本身无关,因为这个问题也发生在 Windows cmd 中,cd c:\.....cd .\....\.. Windows 仍然会让你侥幸逃脱,通过一个点引用两个多于两个点.因为它是从DOS 继承的,将两个以上的点减少为一个并删除尾随空格。

【讨论】:

  • 这充其量只是巧合相关。 os.path.isdiros.stat 的包装器,它(至少在 POSIX 中)在 "..." 上引发错误;它当然不会像".."一样默默对待它。
  • 我的意思是,os.stat 是显然将.. 等同于... 和更长的调用; Python 本身是不可知的。
  • 其实Windows的os.path.isdir是通过调用GetFileAttributes实现的,后者又调用NtQueryAttributesFile。像所有文件系统函数一样,首先它必须将 DOS 路径转换为原生 NT 路径。到内核​​“。”和 ".." 只是普通名称,因此运行时库首先必须通过函数 RtlGetFullPathName_Ustr 对路径进行规范化,os.path.abspath 也使用该函数,因此结果相似。它在最终组件中减少两个以上的点和尾随空格的方式是继承自 DOS 的传统。它正在尽最大努力模仿 1980 年代的操作系统。
  • @eryksun 谢谢!您的评论是迄今为止我认为最正确的,希望您不介意我在答案中引用它。
  • 过度分析运行时库的 DOS 仿真可能会让自己发疯。例如,如果工作目录是“C:\\”,那么os.path.abspath('.../') == 'C:\\...'os.path.abspath('.../.') == 'C:\\'。从逻辑上讲,它们应该是相同的,但在第二种情况下,有一个初始传递可以解决“/。”,因此最终组件规则被应用于“...”,这将其简化为“。”,得到解决了。​​
【解决方案2】:

这是因为现代计算机目录结构中的. 指向当前目录。同样,.. 指向当前目录的父目录。因此,您可以通过在 windows cmd 中键入 cd ..\..\ 在目录结构中向上导航两个文件夹。这不是一个错误,这是一个功能!我现在无法访问 Windows 机器,但 cd ... 在我的 Ubuntu 17.10 笔记本电脑上返回错误 bash: cd: ...: No such file or directory。对于大于 2 的点数,我都会遇到相同的错误。如果 python 返回True...,那是一个错误。我会在你的 cd 命令中添加一些子句,禁止输入超过 2 个点,或者让 4 个点上 2 个目录,6 个点上 3 个目录,依此类推。

【讨论】:

  • 你在普通的 Shell 中运行它。我正在构建自己的 shell,并且正在创建自己的 cd 命令。它使用if os.path.isdir(self.shell.current_dir + dir): 来检查目录是否存在。问题是当它得到c:\\.... 这样的输入时,它返回True,我不知道为什么......
  • 我用我的 shell 作为标准 shell 上发生的事情的一个例子。显然,你可以让你做任何你想做的事情。
  • 当然是的,但问题是if os.path.isdir("c:\\...."): 返回 true.. 据我所知,它不应该这样做,除非有人解释为什么这样做?没有名为....... 等的文件夹。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-17
  • 2021-07-02
  • 1970-01-01
  • 2017-08-02
  • 1970-01-01
  • 2018-11-06
  • 2016-09-03
相关资源
最近更新 更多