如何用Python判断一个目录是否是Windows的符号链接

5
我正在运行os.walk()"C:\Users\confusedDev\Documents"上,我看到["My Music", "My Pictures"...]被返回为子目录,但它们实际上并没有被访问。经过一些研究,我发现它们实际上是Windows中的junctions

我的理解是,junction是一个指向目录的符号链接,默认情况下会被os.walk()忽略,但以下测试未能证明:

>>> os.path.islink("C:\\Users\\confusedDev\\Documents\\My Pictures")
False

嗯... os.walk() 怎么知道"C:\Users\confusedDev\Documents\My Pictures"是一个指向"C:\Users\confusedDev\Pictures"的符号链接并需要跳过呢? 我想调用同样的api...目前,我的解决方法仅假设如果os.walk()跳过一个目录,则它是一个联接点


可能是 os.path.islink on windows with python 的重复问题。 - Grzegorz Oledzki
os.[l]stat 的实现在内部不一致。对于 follow_symlinks,它将任何重分析点处理为链接,而不是正确地限制为仅符号链接和[某些]连接点。此外,在创建 stat 结果时,它仅接受符号链接重分析点作为 S_IFLNK 模式标志,这是 islink 检查的内容。它还应该接受连接点,但仅当它们实现传统链接时,即是目标为 "\?\Volume{...}" 挂载点并且 GetVolumeNameForVolumeMountPoint 将成功时。 - Eryk Sun
1
@GrzegorzOledzki在谈论Windows的“junction links”,而不是符号链接:https://dev59.com/RGox5IYBdhLWcg3wr2Po。它们在Windows中不同。`islink`甚至对于“junction links”在Python3中也返回false。有什么想法可以用Python检查“junction links”吗? - alpha_989
4个回答

9

虽然有点晚了,但是你可以在os.readlink()周围加上try和except语句,以便处理目录联接,并将其放入一个函数中,您可以像这样调用该函数:

def is_junction(path: str) -> bool:
    try:
        return bool(os.readlink(path))
    except OSError:
        return False

3

我将使用的另一种方式是subprocess。只需调用外部Windows程序即可提供有关链接的信息,如果链接存在,则返回0作为返回代码,否则返回其他代码表示不存在或不是链接:

fsutil reparsepoint query "<PathToTest>"

举个例子:

src = "C:\\Windows"
child = subprocess.Popen(
    "fsutil reparsepoint query \"{}\"".format(src),
    stdout=subprocess.PIPE
)
streamdata = child.communicate()[0]
rc = child.returncode

if rc == 0:
    print("Link exists")

在Windows 10中,作为普通用户使用可以正常工作(也可以创建链接),但在Windows 7中需要管理员权限。对我来说不是问题,因为我的应用程序会检查创建新链接所需的权限,在Windows 7中仍然需要管理员权限。

问候!


谢天谢地,你是唯一一个完全正确的人,而不使用不可靠的win32库或ctypes。非常感谢你。我已经使用“dir”有一段时间了。最终我得到了你的好的解决方案。 - Alen Wesker

1
使用python3.5,对于连接点链接islink返回false。似乎python3.5不支持连接点链接,但可以使用ctypes或外部库添加对连接点链接的支持:
  1. 使用ntfs的外部模块:https://github.com/Juntalis/ntfslink-python/tree/master/ntfslink

  2. 在pywin32中使用win32模块:http://docs.activestate.com/activepython/2.5/pywin32/win32file__CreateSymbolicLink_meth.html

  3. 直接调用dlls:https://dev59.com/0XM_5IYBdhLWcg3w-4dg#1143276

以下是更加复杂的解决方案。另外,如果您使用 junction links,它们将无法在之前的Windows版本或其他操作系统上工作。

简而言之,为了使其便携,最好将您的junction links转换为symbolic links,使用mklink /D而不是mklink /Jsymbolic links可以被os.walkos.path.islink识别。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接