Python 跨平台隐藏文件检测

Python 跨平台隐藏文件检测,python,cross-platform,filesystems,Python,Cross Platform,Filesystems,跨平台处理隐藏文件的最佳方法是什么? (最好使用Python,但仍欢迎使用其他解决方案) 只需检查前导“.”就可以用于*nix/Mac,文件属性在Windows上也可以。然而,这似乎有点简单,也没有考虑到隐藏东西的替代方法(.hidden files,等等)。有没有标准的方法来处理这个问题?“有没有标准的方法来处理这个问题?”是的。使用标准(即POSIX兼容)操作系统 因为Windows是非标准的,所以没有适用的标准。如果有,那不是很好吗?我感觉到你的痛苦 任何你试图做的跨平台的事情都会有Win

跨平台处理隐藏文件的最佳方法是什么? (最好使用Python,但仍欢迎使用其他解决方案)

只需检查前导“.”就可以用于*nix/Mac,文件属性在Windows上也可以。然而,这似乎有点简单,也没有考虑到隐藏东西的替代方法(.hidden files,等等)。有没有标准的方法来处理这个问题?

“有没有标准的方法来处理这个问题?”是的。使用标准(即POSIX兼容)操作系统

因为Windows是非标准的,所以没有适用的标准。如果有,那不是很好吗?我感觉到你的痛苦

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


就目前的情况来看,你的解决方案非常好。在将来的某个时候,微软可能会选择编写一个兼容POSIX的操作系统。在那之前,你能很好地应对这种情况。

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

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

它主要相当于您所做的事情,但以一种可插拔、灵活和可扩展的方式


请参见此处的源代码:

这是一个在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
我添加了类似于has_hidden_属性的内容。如果您的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来实现更具Python风格的API。

Jason R.Coombs的答案对于windows来说已经足够了。大多数POSIXGUI文件管理器/打开对话框等可能遵循与
ls
相同的“点前缀表示隐藏”约定。但不是MacOSX

在查找器、文件打开面板等中隐藏文件或目录至少有四种方式:

  • 点前缀
  • HFS+不可见属性
  • 查找信息隐藏标志
  • 匹配CoreFoundation中内置的特殊黑名单(每个操作系统版本都不同,例如,
    ~/Library
    在10.7+中隐藏,但在10.6中不隐藏)
尝试编写自己的代码来处理所有这些并不容易。而且你必须让它保持最新,因为我敢打赌黑名单将随着大多数操作系统版本的变化而改变,Finder信息最终将从不推荐的信息变为完全不受支持的信息,扩展属性的支持范围可能比HFS+更广

但是如果您需要
pyobjc
(它已经包含在最近苹果提供的Python中,并且可以通过
pip
安装),您可以调用苹果的代码:

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或更早版本,目录枚举标志还不存在,因此唯一的选项是过滤
上的
目录路径\u错误\u(或仅
os.listdir
)之类的内容

如果您必须在没有
pyobjc
的情况下生存,您可以下拉到
CoreFoundation
等价物,并使用
ctypes
。关键函数是
cfurlcopyresourcepropertyworkey
CFURLEnumeratorCreateForDirectoryURL
用于列出目录

有关实现,请参阅

我测试过:

  • 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中显示)

它应该适用于任何OSX10.6+和任何Python 2.6+。如果您需要OSX10.5,则需要使用旧的API(或
OS.listdir
)并在
上进行筛选。如果您需要Python2.5,请将
字节检查更改为
str
检查(这当然会破坏3.x),并将
更改为丑陋的
最后尝试
/
或手动释放

如果有人计划将此代码放入库中,我强烈建议首先检查
pyobjc
import Foundation
,如果没有
ImportError
,则获胜),如果不可用,则仅使用
ctypes
代码


最后一点注意:

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

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


这可能无法回答您的问题,例如,他们可能只是将“筛选隐藏文件”标志传递给平台的本机文件浏览器对话框,但您正在尝试构建控制台模式的文件浏览器,但无法做到这一点。但是如果有,就使用它。

结合我之前的答案以及@abarnert的答案,我发布了对隐藏文件检测的跨平台支持。安装该软件包后,要检测任何文件的隐藏状态,只需调用
is\u hidden

from jaraco import path
path.is_hidden(file)

@洛特:我通常喜欢你的评论,但这没有帮助。标准库中还有许多其他模块用于处理Windows的非标准方式。我肯定OP只是在寻找类似的东西。@TechnomalLogical:没错,有些模块可以最小化差异。关键是非标准意味着非标准。这是一个令人沮丧的问题。没有仙尘解决方案,mak