当前位置:  开发笔记 > 编程语言 > 正文

跨平台隐藏文件检测

如何解决《跨平台隐藏文件检测》经验,为你挑选了2个好方法。

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

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



1> Jason R. Coo..:

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


注意:在Python 3.5及更高版本中,Win32文件属性可以通过`os.stat(path).st_file_attributes`直接获得.[参见文档.](https://docs.python.org/3/library/os.html#os.stat_result.st_file_attributes)
我不得不纠正is_hidden,因为它没有在Unix上进行适当的测试.事实上,我甚至不清楚Unix上的正确测试是什么.'..'隐藏了吗?关于什么 '../..'?当然隐藏了特殊名称,但该函数应该解决它吗?为了兼容性,我想是的.我已经改变了`is_hidden`来测试startswith('.')的基本名称.

2> abarnert..:

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

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

点前缀.

HFS +隐形属性.

Finder Info隐藏的标志.

匹配CoreFoundation中内置的特殊黑名单(在每个操作系统版本上都不同 - 例如,~/Library隐藏在10.7+中,但不在10.6中).

尝试编写自己的代码来处理所有这些并不容易.而且你必须保持它是最新的,因为我愿意打赌黑名单会随着大多数操作系统版本而改变,Finder Info最终将从弃用变为完全不受支持,扩展属性可能比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.主要功能是CFURLCopyResourcePropertyForKeyis_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

它适用于每个(例如,它跳过~/Library10.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等)内置了这种支持.(而且,其中许多都是开源的,因此您可以阅读他们的代码以了解他们是如何做到的.)

这可能无法解答您的问题 - 例如,他们可能只是将"过滤器隐藏文件"标记传递给平台的本机文件 - 浏览器对话框,但您正在尝试构建一个控制台模式的文件浏览器而不能这样做.但如果确实如此,那就用吧.

推荐阅读
牛尾巴2010
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有