【问题标题】:os.path.islink on windows with pythonos.path.islink 在 windows 上使用 python
【发布时间】:2013-02-21 21:39:48
【问题描述】:

在带有 Python 2.7 的 Windows 7 上,如何检测路径是否为符号链接? 这不起作用os.path.islink(),它说如果为假或不受支持,它会返回假,并且我提供的路径绝对是符号链接,所以我假设它在 Windows 上不受支持?我能做什么?

【问题讨论】:

  • This 可能会提供一些帮助。
  • 看看jaraco.windows package;它必须使用ctypes 来支持这一点。 Python 3.2 确实正确支持 Windows 符号链接。

标签: python windows symlink pywin32


【解决方案1】:

根本问题是您使用的 Python 版本太旧。如果您想坚持使用 2.x,您将无法利用 2010 年初之后添加的新功能。

其中一项功能是处理 NTFS 符号链接。该功能于 2010 年底在 3.2 中添加。(有关详细信息,请参阅 3.23.12.7 来源。)

在那之前 Python 没有处理 NTFS 符号链接的原因是直到 2009 年底才出现这种情况。(IIRC,6.0 内核中包含支持,但用户空间支持需要 Vista/2008 上的服务包;只有 7 /2008R2 和更新版本是内置的。另外,您需要一个足够新的 MSVCRT 才能访问该用户区支持,并且 Python 有一个明确的政策,即在次要版本中不升级到新的 Visual Studio 版本。)

代码没有移植回 2.x 的原因是 that there will never be a 2.8,并且像 2.7.3(或 2.7.4)这样的错误修复版本没有新功能,只有错误修复。

这已被报告为 issue 13143,预期的修复是更改 2.7 文档以阐明 islink 在 Windows 上始终返回 False

所以,如果你想在 Windows 下读取 NTFS 符号链接,要么升级到 Python 3.2+,要么你必须使用win32apictypes 等自行完成。

或者,正如 Martijn Pieters 建议的那样,与其自己做,不如使用像 jaraco.windows 这样的第三方库来做和/或借用 their code

或者,如果您真的愿意,可以从 3.2 源代码中借用代码并围绕它构建一个 C 扩展模块。如果你从ntpathos 再到nt(实际上是posixmodule.c),我相信它的精髓就在win32_xstat_impl and win32_xstat_impl_w

【讨论】:

  • 你一定是被误导了。使用 NTFS 3.0 的 windows NT 5 (windows 2000) 确实存在重解析点。它很实用。 python 实现只是懒惰或误导。
  • 不适用于 python 3.6 中的目录连接:os.path.islink('c:\\users\\erik\\Local Settings')
【解决方案2】:

这是我最终用来确定文件或目录是否是 Windows 7 中的链接的方法:

from subprocess import check_output, CalledProcessError
import os.path
import ctypes
def isLink(path):
    if os.path.exists(path):
        if os.path.isdir(path):
            FILE_ATTRIBUTE_REPARSE_POINT = 0x0400
            attributes = ctypes.windll.kernel32.GetFileAttributesW(unicode(path))
            return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) > 0
        else:
            command = ['dir', path]
            try:
                with open(os.devnull, 'w') as NULL_FILE:
                    o0 = check_output(command, stderr=NULL_FILE, shell=True)
            except CalledProcessError as e:
                print e.output
                return False
            o1 = [s.strip() for s in o0.split('\n')]
            if len(o1) < 6:
                return False
            else:
                return 'SYMLINK' in o1[5]
    else:
        return False

编辑:根据 Zitrax 和 Annan 的建议修改代码

编辑:根据 shioko 的建议添加了包含语句

【讨论】:

  • 当文件不存在时,值得从check_output 捕获CalledProcessErrors。您还可以通过stderr=subprocess.PIPE 隐藏错误输出到标准输入。这个解决方案真的很hacky,但比其他答案更可行。
  • 此答案无法检查目录是否为链接,因为 dir 命令只会列出内容。
  • 你在哪里导入unicode函数?您应该包括所有导入语句。
  • 谢谢@shioko。不完整的代码很烦人。纠正了疏忽。
【解决方案3】:

对于目录:

import os, ctypes
def IsSymlink(path):
    FILE_ATTRIBUTE_REPARSE_POINT = 0x0400
    return os.path.isdir(path) and (ctypes.windll.kernel32.GetFileAttributesW(unicode(path)) & FILE_ATTRIBUTE_REPARSE_POINT):

Source

【讨论】:

  • 源已死
  • 比较您缺少返回语句的来源。您可以检查结果是否 > 0 否则结果为 1024
【解决方案4】:

您还可以使用 pywin32 模块:GetFileAttributeswin32api 子模块中可用,FILE_ATTRIBUTE_REPARSE_POINTwin32con 模块中可用。例如,要测试给定路径是否是目录的符号链接,代码变为:

import os
import win32api
import win32con

def is_directory_symlink(path):
    return bool(os.path.isdir(path) 
                and (win32api.GetFileAttributes(path) &
                     win32con.FILE_ATTRIBUTE_REPARSE_POINT))

如果使用 Python 2 并且路径可能包含非 ascii 字符,GetFileAttributes 需要一个 unicode 字符串。但是,简单地使用unicode(path) 通常会失败:您应该测试path 是否为str,如果是,请使用其decode 方法。

【讨论】:

    【解决方案5】:

    只使用if file[-4:len(file)] != ".lnk": 对我有用

    【讨论】:

    • 这被否决了,因为用户询问的是重解析点,而不是 .lnk 文件
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-06
    • 2016-07-16
    • 2011-02-08
    • 2013-06-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多