在带有 Python 2.7 的 Windows 7 上,如何检测路径是否为符号链接?这不起作用os.path.islink()
,它说如果 false 或不支持它会返回 false 并且我提供的路径绝对是符号链接,所以我假设它在 windows 上不受支持?我能做些什么?
5 回答
根本问题是您使用的 Python 版本太旧。如果您想坚持使用 2.x,您将无法利用 2010 年初之后添加的新功能。
其中一项功能是处理 NTFS 符号链接。该功能于 2010 年底在 3.2 中添加。(有关详细信息,请参阅3.2、3.1和2.7源代码。)
在那之前 Python 没有处理 NTFS 符号链接的原因是直到 2009 年底才出现这种情况。(IIRC,支持包含在 6.0 内核中,但用户态支持需要 Vista/2008 上的服务包;只有 7/2008R2 和较新的内置了它。另外,您需要一个足够新的 MSVCRT 才能访问该用户区支持,并且 Python 有一个明确的政策,即在次要版本中不升级到新的 Visual Studio 版本。)
代码没有移植回 2.x 的原因是永远不会有 2.8,并且像 2.7.3(或 2.7.4)这样的错误修复版本没有新功能,只有错误修复。
这已报告为问题 13143,并且预期的修复是更改 2.7 文档以澄清islink
始终False
在 Windows 上返回。
所以,如果你想在 Windows 下阅读 NTFS 符号链接,要么升级到 Python 3.2+,要么你必须使用win32api
,ctypes
等自行完成。
或者,正如 Martijn Pieters 所建议的那样,与其自己做,不如使用第三方库jaraco.windows
和/或借用他们的代码。
或者,如果您真的愿意,可以从 3.2 源代码中借用代码并围绕它构建一个 C 扩展模块。如果您从ntpath
to 到os
to nt
(实际上是posixmodule.c
),我相信它的胆量在win32_xstat_impl
andwin32_xstat_impl_w
中。
这就是我最终用来确定文件或目录是否是 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 的建议添加了包含语句
对于目录:
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):
也可以使用 pywin32 模块:GetFileAttributes
在win32api
子模块和模块FILE_ATTRIBUTE_REPARSE_POINT
中都有win32con
。例如,要测试给定路径是否是目录的符号链接,代码变为:
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)
通常会失败:您应该测试 ifpath
是 a str
,如果是,则使用它的decode
方法。
只为我使用if file[-4:len(file)] != ".lnk":
作品