python 跨平台隐藏文件检测

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/284115/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 19:48:51  来源:igfitidea点击:

Cross platform hidden file detection

pythoncross-platformfilesystems

提问by Kai

What is the best way to do cross-platform handling of hidden files? (preferably in Python, but other solutions still appreciated)

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

Simply checking for a leading '.' works for *nix/Mac, and file attributes work on Windows. However, this seems a little simplistic, and also doesn't account for alternative methods of hiding things (.hidden files, etc.). Is there a standard way to deal with this?

只需检查前导 '.' 适用于 *nix/Mac,文件属性适用于 Windows。然而,这似乎有点简单,并且也没有考虑隐藏事物的替代方法(.hidden 文件等)。有没有标准的方法来处理这个问题?

采纳答案by Ali Afshar

We actually address this in a project we write. What we do is have a number of different "hidden file checkers" that are registered with a main checker. We pass each file through these to see if it should be hidden or not.

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

These checkers are not only for different OS's etc, but we plug into version control "ignored" files, and optional user overrides by glob or regular expression.

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

It mostly amounts to what you have done, but in a pluggable, flexible and extensible way.

它主要与您所做的相同,但是以可插拔、灵活和可扩展的方式。

See source code here: https://bitbucket.org/aafshar/pida-main/src/tip/pida/services/filemanager/filemanager.py

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

回答by Jason R. Coombs

Here's a script that runs on Python 2.5+ and should do what you're looking for:

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

I added something similar to has_hidden_attribute to jaraco.windows. If you have jaraco.windows >= 2.3:

我在 jaraco.windows 中添加了类似于 has_hidden_​​attribute 的东西。如果您有 jaraco.windows >= 2.3:

from jaraco.windows import filesystem

def has_hidden_attribute(filepath):
    return filesystem.GetFileAttributes(filepath).hidden

As Ben has pointed out, on Python 3.5, you can use the stdlib:

正如 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)

Though you may still want to use jaraco.windows for the more Pythonic API.

尽管您可能仍想使用 jaraco.windows 来获取更多 Pythonic API。

回答by abarnert

Jason R. Coombs's answer is sufficient for Windows. And most POSIX GUI file managers/open dialogs/etc. probably follow the same "dot-prefix-means-hidden" convention as ls. But not Mac OS X.

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

There are at least four ways a file or directory can be hidden in Finder, file open panels, etc.:

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

  • Dot prefix.
  • HFS+ invisible attribute.
  • Finder Info hidden flag.
  • Matches a special blacklist built into CoreFoundation (which is different on each OS version—e.g., ~/Libraryis hidden in 10.7+, but not in 10.6).
  • 点前缀。
  • HFS+ 隐形属性。
  • Finder 信息隐藏标志。
  • 匹配 CoreFoundation 内置的特殊黑名单(每个操作系统版本都不同——例如,~/Library在 10.7+ 中隐藏,但在 10.6 中不隐藏)。

Trying to write your own code to handle all of that is not going to be easy. And you'll have to keep it up-to-date, as I'm willing to bet the blacklist will change with most OS versions, Finder Info will eventually go from deprecated to completely unsupported, extended attributes may be supported more broadly than HFS+, …

尝试编写自己的代码来处理所有这些并不容易。而且你必须让它保持最新,因为我敢打赌黑名单会随着大多数操作系统版本而改变,Finder Info 最终将从弃用变为完全不受支持,扩展属性可能比 HFS+ 得到更广泛的支持, ...

But if you can require pyobjc(which is already included with recent Apple-supplied Python, and can be installed via pipotherwise), you can just call Apple's code:

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

This should work on any Python that pyobjc supports, on OS X 10.6+. If you want 10.5 or earlier, directory enumeration flags didn't exist yet, so the only option is something like filtering something like contentsOfDirectoryAtPath_error_(or just os.listdir) on is_hidden.

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

If you have to get by without pyobjc, you can drop down to the CoreFoundationequivalents, and use ctypes. The key functions are CFURLCopyResourcePropertyForKeyfor is_hiddenand CFURLEnumeratorCreateForDirectoryURLfor listing a directory.

如果您必须不使用pyobjc,则可以下拉到CoreFoundation等效项,然后使用ctypes. 关键功能是CFURLCopyResourcePropertyForKey用于is_hiddenCFURLEnumeratorCreateForDirectoryURL用于列出目录。

See http://pastebin.com/aCUwTumBfor an implementation.

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

I've tested with:

我已经测试过:

  • OS X 10.6, 32-bit python.org 3.3.0
  • OS X 10.8, 32-bit Apple 2.7.2
  • OS X 10.8, 64-bit Apple 2.7.2
  • OS X 10.8, 64-bit python.org 3.3.0
  • 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

It works as appropriate on each (e.g., it skips ~/Libraryon 10.8, but shows it on 10.6).

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

It shouldwork on any OS X 10.6+ and any Python 2.6+. If you need OS X 10.5, you need to use the old APIs (or os.listdir) and filter on is_hidden. If you need Python 2.5, change the byteschecks to strchecks (which of course breaks 3.x) and the withto an ugly try/finallyor manual releasing.

应该适用于任何 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或手动发布。

If anyone plans on putting this code into a library, I would strongly suggest checking for pyobjcfirst (import Foundationand, if you don't get an ImportErroryou win), and only using the ctypescode if it's not available.

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



One last note:

最后一点:

Some people looking for this answer are trying to reinvent a wheel they don't need to.

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

Often, when people are doing something like this, they're building a GUI and want to, e.g., show a file browsers with an option to hide or show hidden files. Many of the popular cross-platform GUI frameworks (Qt, wx, etc.) have this support built in. (Also, many of them are open source, so you can read their code to see how they do it.)

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

That may not answer your question—e.g., they may just be passing a "filter hidden files" flag to the platform's native file-browser dialog, but you're trying to build a console-mode file-browser and can't do that. But if it does, just use it.

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

回答by Jason R. Coombs

Incorporating my previous answer as well as that from @abarnert, I've released jaraco.path 1.1with cross-platform support for hidden file detection. With that package installed, to detect the hidden state of any file, simply invoke is_hidden:

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

from jaraco import path
path.is_hidden(file)

回答by S.Lott

"Is there a standard way to deal with this?" Yes. Use a standard (i.e., POSIX-compliant) OS.

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

Since Windows is non-standard -- well -- there's no applicable standard. Wouldn't it be great if there was? I feel your pain.

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

Anything you try to do that's cross-platform like that will have Win32 oddities.

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

Your solution is -- for the present state of affairs -- excellent. At some point in the future, Microsoft may elect to write a POSIX-compliant OS. Until then, you're coping well with the situation.

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