对隐藏文件进行跨平台处理的最佳方法是什么?(最好是在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文件管理器/打开对话框/等.可能遵循相同的"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
.主要功能是CFURLCopyResourcePropertyForKey
对is_hidden
和CFURLEnumeratorCreateForDirectoryURL
用于列出一个目录.
有关实现,请参见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
它适用于每个(例如,它跳过~/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等)内置了这种支持.(而且,其中许多都是开源的,因此您可以阅读他们的代码以了解他们是如何做到的.)
这可能无法解答您的问题 - 例如,他们可能只是将"过滤器隐藏文件"标记传递给平台的本机文件 - 浏览器对话框,但您正在尝试构建一个控制台模式的文件浏览器而不能这样做.但如果确实如此,那就用吧.