21

跨平台处理隐藏文件的最佳方法是什么?(最好在 Python 中,但仍然赞赏其他解决方案)

只需检查一个领先的“。” 适用于 *nix/Mac,文件属性适用于 Windows。然而,这似乎有点简单,也没有考虑隐藏东西的替代方法(.hidden 文件等)。有没有标准的方法来处理这个?

4

5 回答 5

22

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

于 2011-06-15T22:37:28.717 回答
11

Jason R. Coombs 的回答对于 Windows 来说已经足够了。和大多数 POSIX GUI 文件管理器/打开对话框/等。可能遵循与ls. 但不是 Mac OS X。

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

  • 点前缀。
  • HFS+ 隐形属性。
  • Finder 信息隐藏标志。
  • 匹配 CoreFoundation 中内置的特殊黑名单(每个操作系统版本都不同——例如,~/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_hiddenCFURLEnumeratorCreateForDirectoryURL用于列出目录。

有关实现,请参见http://pastebin.com/aCUwTumB

我已经测试过:

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

它适用于每一个(例如,它~/Library在 10.8 上跳过,但在 10.6 上显示)。

应该适用于任何 OS X 10.6+ 和任何 Python 2.6+。如果您需要 OS X 10.5,则需要使用旧 API(或os.listdir)并在is_hidden. 如果您需要 Python 2.5,请将检查更改bytesstr检查(这当然会破坏 3.x)并将检查更改with为丑陋try/finally或手动发布。

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


最后一点:

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

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

这可能无法回答您的问题 - 例如,他们可能只是将“过滤隐藏文件”标志传递给平台的本机文件浏览器对话框,但您正在尝试构建控制台模式文件浏览器并且不能这样做. 但如果是这样,请使用它。

于 2013-03-05T23:42:04.087 回答
2

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

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

它主要相当于你所做的,但以一种可插入、灵活和可扩展的方式。

在此处查看源代码:https ://bitbucket.org/aafshar/pida-main/src/tip/pida/services/filemanager/filemanager.py

于 2008-11-12T16:11:11.150 回答
0

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

from jaraco import path
path.is_hidden(file)
于 2015-06-29T08:43:15.290 回答
-4

“有标准的方法来处理这个吗?” 是的。使用标准(即符合 POSIX 的)操作系统。

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

你尝试做的任何跨平台的事情都会有 Win32 的奇怪之处。

你的解决方案——就目前的情况而言——非常好。在未来的某个时候,Microsoft 可能会选择编写符合 POSIX 的操作系统。在那之前,你可以很好地应对这种情况。

于 2008-11-12T15:47:54.550 回答