使用 os.walk 避免无限递归
Avoiding infinite recursion with os.walk
我将 os.walk
与 followlinks=True
一起使用,但我遇到了一个符号 link 引用它自己的目录的地方,导致无限循环。在这种情况下,罪魁祸首是 /usr/bin/X11
列表如下:
lrwxrwxrwx 1 root root 1 Apr 24 2015 X11 -> .
有什么方法可以避免跟随 link 到 .
或 ..
,我认为这会导致类似的问题?我想我可以用 os.readlink
检查一下,然后与当前路径进行比较。还有其他解决方案吗?
为了完全避免无限递归的问题(links 指向任何地方)你需要存储文件 and/or 你已经访问过的目录。
来自 pynotify 模块的人遇到了同样的问题并使用了描述的方法。补丁在 link ;)
如果要避免递归,就无法避免存储一组所有访问过的目录。您不需要使用 readlink
,但是,您可以只存储 inode。这完全避免了路径规范化的问题。
import os
dirs = set()
for dirpath, dirnames, filenames in os.walk('.', followlinks=True):
st = os.stat(dirpath)
scandirs = []
for dirname in dirnames:
st = os.stat(os.path.join(dirpath, dirname))
dirkey = st.st_dev, st.st_ino
if dirkey not in dirs:
dirs.add(dirkey)
scandirs.append(dirname)
dirnames[:] = scandirs
print(dirpath)
我将 os.walk
与 followlinks=True
一起使用,但我遇到了一个符号 link 引用它自己的目录的地方,导致无限循环。在这种情况下,罪魁祸首是 /usr/bin/X11
列表如下:
lrwxrwxrwx 1 root root 1 Apr 24 2015 X11 -> .
有什么方法可以避免跟随 link 到 .
或 ..
,我认为这会导致类似的问题?我想我可以用 os.readlink
检查一下,然后与当前路径进行比较。还有其他解决方案吗?
为了完全避免无限递归的问题(links 指向任何地方)你需要存储文件 and/or 你已经访问过的目录。
来自 pynotify 模块的人遇到了同样的问题并使用了描述的方法。补丁在 link ;)
如果要避免递归,就无法避免存储一组所有访问过的目录。您不需要使用 readlink
,但是,您可以只存储 inode。这完全避免了路径规范化的问题。
import os
dirs = set()
for dirpath, dirnames, filenames in os.walk('.', followlinks=True):
st = os.stat(dirpath)
scandirs = []
for dirname in dirnames:
st = os.stat(os.path.join(dirpath, dirname))
dirkey = st.st_dev, st.st_ino
if dirkey not in dirs:
dirs.add(dirkey)
scandirs.append(dirname)
dirnames[:] = scandirs
print(dirpath)