跨平台处理隐藏文件的最佳方法是什么?(最好在 Python 中,但仍然赞赏其他解决方案)
只需检查一个领先的“。” 适用于 *nix/Mac,文件属性适用于 Windows。然而,这似乎有点简单,也没有考虑隐藏东西的替代方法(.hidden 文件等)。有没有标准的方法来处理这个?
跨平台处理隐藏文件的最佳方法是什么?(最好在 Python 中,但仍然赞赏其他解决方案)
只需检查一个领先的“。” 适用于 *nix/Mac,文件属性适用于 Windows。然而,这似乎有点简单,也没有考虑隐藏东西的替代方法(.hidden 文件等)。有没有标准的方法来处理这个?
这是一个在 Python 2.5+ 上运行的脚本,应该可以满足您的需求:
import ctypes
import os
def is_hidden(filepath):
name = os.path.basename(os.path.abspath(filepath))
return name.startswith('.') or has_hidden_attribute(filepath)
def has_hidden_attribute(filepath):
try:
attrs = ctypes.windll.kernel32.GetFileAttributesW(unicode(filepath))
assert attrs != -1
result = bool(attrs & 2)
except (AttributeError, AssertionError):
result = False
return result
我在 jaraco.windows 添加了类似于 has_hidden_ attribute的内容。如果您有 jaraco.windows >= 2.3:
from jaraco.windows import filesystem
def has_hidden_attribute(filepath):
return filesystem.GetFileAttributes(filepath).hidden
正如 Ben 所指出的,在 Python 3.5 上,您可以使用 stdlib:
import os, stat
def has_hidden_attribute(filepath):
return bool(os.stat(filepath).st_file_attributes & stat.FILE_ATTRIBUTE_HIDDEN)
尽管您可能仍希望将 jaraco.windows 用于更多 Pythonic API。
Jason R. Coombs 的回答对于 Windows 来说已经足够了。和大多数 POSIX GUI 文件管理器/打开对话框/等。可能遵循与ls
. 但不是 Mac OS X。
至少有四种方法可以在 Finder、文件打开面板等中隐藏文件或目录:
~/Library
在 10.7+ 中隐藏,但在 10.6 中没有)。尝试编写自己的代码来处理所有这些并不容易。而且你必须保持最新,因为我愿意打赌黑名单会随着大多数操作系统版本而改变,Finder Info 最终会从弃用变为完全不受支持,扩展属性可能比 HFS+ 得到更广泛的支持,……</p>
但是如果你可以要求pyobjc
(它已经包含在最近的 Apple 提供的 Python 中,并且可以通过pip
其他方式安装),你可以调用 Apple 的代码:
import Foundation
def is_hidden(path):
url = Foundation.NSURL.fileURLWithPath_(path)
return url.getResourceValue_forKey_error_(None, Foundation.NSURLIsHiddenKey, None)[0]
def listdir_skipping_hidden(path):
url = Foundation.NSURL.fileURLWithPath_(path)
fm = Foundation.NSFileManager.defaultManager()
urls = fm.contentsOfDirectoryAtURL_includingPropertiesForKeys_options_error_(
url, [], Foundation.NSDirectoryEnumerationSkipsHiddenFiles, None)[0]
return [u.path() for u in urls]
这应该适用于 pyobjc 支持的任何 Python,在 OS X 10.6+ 上。如果您想要 10.5 或更早版本,则目录枚举标志尚不存在,因此唯一的选择是过滤类似contentsOfDirectoryAtPath_error_
(或只是os.listdir
) on之类的东西is_hidden
。
pyobjc
如果您必须不CoreFoundation
使用ctypes
. 主要功能是CFURLCopyResourcePropertyForKey
用于is_hidden
和CFURLEnumeratorCreateForDirectoryURL
用于列出目录。
有关实现,请参见http://pastebin.com/aCUwTumB。
我已经测试过:
它适用于每一个(例如,它~/Library
在 10.8 上跳过,但在 10.6 上显示)。
它应该适用于任何 OS X 10.6+ 和任何 Python 2.6+。如果您需要 OS X 10.5,则需要使用旧 API(或os.listdir
)并在is_hidden
. 如果您需要 Python 2.5,请将检查更改bytes
为str
检查(这当然会破坏 3.x)并将检查更改with
为丑陋try
/finally
或手动发布。
如果有人计划将此代码放入库中,我强烈建议pyobjc
首先检查(import Foundation
并且,如果您没有获得ImportError
胜利),并且仅在ctypes
代码不可用时才使用该代码。
最后一点:
一些寻找这个答案的人正试图重新发明一个他们不需要的轮子。
通常,当人们在做这样的事情时,他们正在构建一个 GUI 并希望,例如,显示一个文件浏览器,并带有隐藏或显示隐藏文件的选项。许多流行的跨平台 GUI 框架(Qt、wx 等)都内置了这种支持。(此外,其中许多是开源的,因此您可以阅读他们的代码以了解他们是如何做到的。)
这可能无法回答您的问题 - 例如,他们可能只是将“过滤隐藏文件”标志传递给平台的本机文件浏览器对话框,但您正在尝试构建控制台模式文件浏览器并且不能这样做. 但如果是这样,请使用它。
我们实际上在我们编写的项目中解决了这个问题。我们所做的是拥有许多不同的“隐藏文件检查器”,它们在主检查器中注册。我们通过这些传递每个文件,看看它是否应该被隐藏。
这些检查器不仅适用于不同的操作系统等,而且我们插入版本控制“忽略”文件,以及通过 glob 或正则表达式可选的用户覆盖。
它主要相当于你所做的,但以一种可插入、灵活和可扩展的方式。
在此处查看源代码:https ://bitbucket.org/aafshar/pida-main/src/tip/pida/services/filemanager/filemanager.py
结合我之前的答案以及来自@abarnert 的答案,我发布了具有跨平台隐藏文件检测支持的jaraco.path 1.1 。安装该软件包后,要检测任何文件的隐藏状态,只需调用is_hidden
:
from jaraco import path
path.is_hidden(file)
“有标准的方法来处理这个吗?” 是的。使用标准(即符合 POSIX 的)操作系统。
由于 Windows 是非标准的——好吧——没有适用的标准。如果有的话不是很好吗?我感觉到你的痛苦。
你尝试做的任何跨平台的事情都会有 Win32 的奇怪之处。
你的解决方案——就目前的情况而言——非常好。在未来的某个时候,Microsoft 可能会选择编写符合 POSIX 的操作系统。在那之前,你可以很好地应对这种情况。