跨平台隐藏文件检测

时间:2008-11-12 14:35:30

标签: python cross-platform filesystems

对隐藏文件进行跨平台处理的最佳方法是什么? (最好是在Python中,但其他解决方案仍然很受欢迎)

只需检查领先的'。'适用于* nix / Mac,文件属性适用于Windows。但是,这看起来有点简单,也没有考虑隐藏事物的替代方法(.hidden文件等)。有没有一种标准的方法可以解决这个问题?

5 个答案:

答案 0 :(得分:19)

这是一个在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。

答案 1 :(得分:9)

Jason R. Coombs的答案足以满足Windows的需求。和大多数POSIX GUI文件管理器/打开对话框/等。可能遵循与ls相同的“dot-prefix-means-hidden”约定。但不是Mac OS X.

至少有四种方法可以在Finder,文件打开面板等中隐藏文件或目录:

  • 点前缀。
  • HFS +隐形属性。
  • Finder Info隐藏标志。
  • 匹配CoreFoundation中内置的特殊黑名单(在每个操作系统版本上都不同 - 例如,~/Library隐藏在10.7+中,但不在10.6中。)

尝试编写自己的代码来处理所有这些并不容易。而且你必须保持它最新的,因为我愿意打赌黑名单与大多数操作系统版本更改,查找信息最终将过时的去完全不支持,扩展属性,可以更广泛地比HFS +支持,...

但是如果您可以要求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]

这应该适用于OS X 10.6+上pyobjc支持的任何Python。如果您想要10.5或更早版本,目录枚举标志尚不存在,因此唯一的选择就是在contentsOfDirectoryAtPath_error_上过滤诸如os.listdir(或仅is_hidden)之类的内容。

如果您必须在没有pyobjc的情况下离开,则可以下拉到CoreFoundation等效项,然后使用ctypes。关键功能是CFURLCopyResourcePropertyForKey is_hiddenCFURLEnumeratorCreateForDirectoryURL列出目录。

有关实施,请参阅http://pastebin.com/aCUwTumB

我测试过:

  • OS X 10.6,32位python.org 3.3.0
  • OS X 10.8,32位Apple 2.7.2
  • OS X 10.8,64位Apple 2.7.2
  • OS X 10.8,64位python.org 3.3.0

它适用于每个(例如,它在10.8上跳过~/Library,但在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 / {{1}或手动释放。

如果有人计划将此代码放入库中,我强烈建议您首先检查finallypyobjc,如果您没有获得import Foundation,则并且仅在ImportError代码不可用时才使用。


最后一点:

有些寻找这个答案的人正试图重新发明他们不需要的轮子。

通常,当人们做这样的事情时,他们正在构建一个GUI,并希望例如向文件浏览器显示隐藏或显示隐藏文件的选项。许多流行的跨平台GUI框架(Qt,wx等)内置了这种支持。(而且,其中许多都是开源的,因此您可以阅读他们的代码以了解他们是如何做到的。)

这可能无法解答您的问题 - 例如,他们可能只是将“过滤器隐藏文件”标记传递给平台的本机文件 - 浏览器对话框,但您正在尝试构建一个控制台模式的文件浏览器并且可以'那样做。但如果确实如此,只需使用它。

答案 2 :(得分:3)

我们实际上是在我们编写的项目中解决这个问题。我们所做的是有一些不同的“隐藏文件检查器”,它们在主检查器中注册。我们通过这些文件来查看它是否应该被隐藏。

这些检查器不仅适用于不同的操作系统等,而且我们可以插入版本控制“忽略”文件,并通过glob或正则表达式插入可选的用户覆盖。

它主要取决于你所做的,但是以可插拔,灵活和可扩展的方式。

请参阅此处的源代码:https://bitbucket.org/aafshar/pida-main/src/tip/pida/services/filemanager/filemanager.py

答案 3 :(得分:0)

结合我以前的答案以及来自@abarnert的答案,我发布了jaraco.path 1.1,支持隐藏文件检测的跨平台支持。安装该软件包后,要检测任何文件的隐藏状态,只需调用is_hidden

即可
from jaraco import path
path.is_hidden(file)

答案 4 :(得分:-3)

“有没有一种标准的方法可以解决这个问题?”是。使用标准(即POSIX兼容)操作系统。

由于Windows是非标准的 - 好 - 没有适用的标准。如果有的话不是很好吗?我感觉到你的痛苦。

你尝试做的任何跨平台的东西都会让Win32变得奇怪。

你的解决方案是 - 对于目前的状况 - 非常好。在未来的某个时候,Microsoft可能会选择编写符合POSIX标准的操作系统。在此之前,你正在应对这种情况。