python - watcher - Detección de archivos ocultos en varias plataformas
python watchdog example (5)
¿Cuál es la mejor manera de manejar archivos ocultos en plataformas cruzadas? (preferiblemente en Python, pero aún se aprecian otras soluciones)
Simplemente buscando un líder ''.'' funciona para * nix / Mac, y los atributos de archivo funcionan en Windows. Sin embargo, esto parece un poco simplista, y tampoco da cuenta de métodos alternativos para ocultar cosas (archivos ocultos, etc.). ¿Hay una forma estándar de lidiar con esto?
"¿Hay una forma estándar de lidiar con esto?" Sí. Use un sistema operativo estándar (es decir, compatible con POSIX).
Como Windows no es estándar, bueno, no hay un estándar aplicable. ¿No sería genial si hubiera? Siento tu dolor.
Cualquier cosa que intentes hacer que sea multiplataforma como esa tendrá las rarezas de Win32.
Su solución es, para el estado actual de las cosas, excelente. En algún momento en el futuro, Microsoft puede optar por escribir un sistema operativo compatible con POSIX. Hasta entonces, estás lidiando bien con la situación.
La respuesta de Jason R. Coombs es suficiente para Windows. Y la mayoría de los administradores de archivos de GUI de POSIX / abrir diálogos / etc. probablemente siga la misma convención "dot-prefix-means-hidden" como ls
. Pero no Mac OS X.
Hay al menos cuatro formas en que un archivo o directorio puede estar oculto en Finder, paneles abiertos de archivos, etc.
- Prefijo de punto
- HFS + atributo invisible.
- Indicador oculto de información del buscador.
- Coincide con una lista negra especial integrada en CoreFoundation (que es diferente en cada versión del sistema operativo, por ejemplo,
~/Library
está oculta en 10.7 o más, pero no en 10.6).
Intentar escribir tu propio código para manejar todo eso no va a ser fácil. Y tendrá que mantenerlo actualizado, ya que estoy dispuesto a apostar a que la lista negra cambiará con la mayoría de las versiones del sistema operativo, Finder Info eventualmente pasará de obsoleto a completamente no compatible, los atributos extendidos pueden ser soportados más ampliamente que HFS + , ...
Pero si puede requerir pyobjc
(que ya está incluido con el último Python suministrado por Apple, y puede instalarse a través de pip
), puede simplemente llamar al código de 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]
Esto debería funcionar en cualquier Python compatible con pyobjc, en OS X 10.6+. Si quiere 10.5 o una versión anterior, los indicadores de enumeración de directorios todavía no existían, por lo que la única opción es algo así como filtrar algo como contentsOfDirectoryAtPath_error_
(o simplemente os.listdir
) on is_hidden
.
Si tiene que arreglárselas sin pyobjc
, puede ir a los equivalentes de CoreFoundation
y usar ctypes
. Las funciones clave son CFURLCopyResourcePropertyForKey
para is_hidden
y CFURLEnumeratorCreateForDirectoryURL
para listar un directorio.
Ver http://pastebin.com/aCUwTumB para una implementación.
He probado con:
- OS X 10.6, 32 bits python.org 3.3.0
- OS X 10.8, 32 bits Apple 2.7.2
- OS X 10.8, Apple de 64 bits 2.7.2
- OS X 10.8, 64-bit python.org 3.3.0
Funciona según corresponda en cada uno (por ejemplo, omite ~/Library
en 10.8, pero lo muestra en 10.6).
Debería funcionar en cualquier OS X 10.6+ y cualquier Python 2.6+. Si necesita OS X 10.5, necesita usar las antiguas API (o os.listdir
) y filtrar is_hidden
. Si necesita Python 2.5, cambie las comprobaciones de bytes
cheques str
(que, por supuesto, se rompen 3.x) y a un feo try
/ finally
o release manual.
Si alguien planea poner este código en una biblioteca, le sugiero que compruebe primero pyobjc
( import Foundation
y, si no obtiene un ImportError
que gana), y solo usar el código ctypes
si no está disponible.
Una última nota:
Algunas personas que buscan esta respuesta intentan reinventar una rueda que no necesitan.
A menudo, cuando las personas hacen algo como esto, están construyendo una GUI y quieren, por ejemplo, mostrar un explorador de archivos con una opción para ocultar o mostrar los archivos ocultos. Muchos de los populares marcos de GUI multiplataforma (Qt, wx, etc.) tienen incorporado este soporte. (Además, muchos de ellos son de código abierto, por lo que puede leer su código para ver cómo lo hacen).
Puede que no responda tu pregunta, por ejemplo, pueden estar pasando un indicador de "filtro de archivos ocultos" al diálogo del navegador de archivos nativo de la plataforma, pero estás intentando construir un navegador de archivos en modo consola y no puedes hacer eso . Pero si lo hace, solo úsalo.
Al incorporar mi respuesta anterior y la de @abarnert, he lanzado jaraco.path 1.1 con soporte multiplataforma para la detección de archivos ocultos. Con ese paquete instalado, para detectar el estado oculto de cualquier archivo, simplemente invoque is_hidden
:
from jaraco import path
path.is_hidden(file)
Aquí hay un script que se ejecuta en Python 2.5+ y debe hacer lo que está buscando:
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
Agregué algo similar a has_hidden_attribute a jaraco.windows . Si tiene jaraco.windows> = 2.3:
from jaraco.windows import filesystem
def has_hidden_attribute(filepath):
return filesystem.GetFileAttributes(filepath).hidden
Como ha señalado Ben, en Python 3.5, puede usar stdlib:
import os, stat
def has_hidden_attribute(filepath):
return bool(os.stat(filepath).st_file_attributes & stat.FILE_ATTRIBUTE_HIDDEN)
Aunque es posible que desee utilizar jaraco.windows para la API más Pythonic.
En realidad abordamos esto en un proyecto que escribimos. Lo que hacemos es tener varios "revisores de archivos ocultos" diferentes que están registrados con un corrector principal. Pasamos cada archivo a través de estos para ver si debe estar oculto o no.
Estas comprobaciones no son solo para sistemas operativos diferentes, etc., sino que nos conectamos a los archivos "ignorados" de control de versiones y a los reemplazos de usuario opcionales por expresiones regulares o glob.
En su mayoría equivale a lo que ha hecho, pero de una manera conectable, flexible y extensible.
Vea el código fuente aquí: https://bitbucket.org/aafshar/pida-main/src/tip/pida/services/filemanager/filemanager.py