25 Stimmen

Plattformübergreifende Erkennung versteckter Dateien

Wie kann man versteckte Dateien am besten plattformübergreifend behandeln? (vorzugsweise in Python, aber auch andere Lösungen sind willkommen)

Die einfache Überprüfung auf ein führendes '.' funktioniert unter *nix/Mac, und die Dateiattribute funktionieren unter Windows. Dies scheint jedoch ein wenig vereinfachend zu sein und berücksichtigt auch keine alternativen Methoden, um Dinge zu verstecken (.hidden files, etc.). Gibt es eine Standardmethode, um damit umzugehen?

23voto

Jason R. Coombs Punkte 38667

Hier ist ein Skript, das auf Python 2.5+ läuft und das tun sollte, wonach Sie suchen:

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

Ich habe etwas Ähnliches wie has_hidden_attribute zu jaraco.Windows . Wenn Sie jaraco.Windows >= 2.3 haben:

from jaraco.windows import filesystem

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

Wie Ben bereits erwähnt hat, können Sie unter Python 3.5 die stdlib verwenden:

import os, stat

def has_hidden_attribute(filepath):
    return bool(os.stat(filepath).st_file_attributes & stat.FILE_ATTRIBUTE_HIDDEN)

Sie können aber auch jaraco.Windows für die Pythonic-API verwenden.

11voto

abarnert Punkte 332066

Die Antwort von Jason R. Coombs ist für Windows ausreichend. Und die meisten POSIX-GUI-Dateimanager/Öffnungsdialoge/etc. folgen wahrscheinlich der gleichen "dot-prefix-means-hidden"-Konvention wie ls . Aber nicht Mac OS X.

Es gibt mindestens vier Möglichkeiten, wie eine Datei oder ein Verzeichnis im Finder, in den Datei-Öffnungsfenstern usw. versteckt werden kann:

  • Punkt-Präfix.
  • HFS+ unsichtbares Attribut.
  • Finder Info versteckte Flagge.
  • Entspricht einer speziellen, in CoreFoundation eingebauten schwarzen Liste (die je nach Betriebssystemversion unterschiedlich ist - z.B., ~/Library ist in 10.7+ versteckt, aber nicht in 10.6).

Der Versuch, einen eigenen Code zu schreiben, um all das zu bewältigen, wird nicht einfach sein. Und Sie müssen ihn auf dem neuesten Stand halten, da ich darauf wette, dass sich die schwarze Liste mit den meisten Betriebssystemversionen ändert, dass Finder Info irgendwann von veraltet zu komplett nicht mehr unterstützt wird, dass erweiterte Attribute breiter unterstützt werden als HFS+,

Aber wenn Sie verlangen können pyobjc (das bereits im aktuellen, von Apple gelieferten Python enthalten ist und über pip sonst), können Sie einfach den Code von Apple aufrufen:

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]

Dies sollte mit jedem Python, das pyobjc unterstützt, unter OS X 10.6+ funktionieren. Wenn Sie 10.5 oder früher wollen, gibt es noch keine Verzeichnisaufzählungsflags, so dass die einzige Möglichkeit darin besteht, etwas zu filtern wie contentsOfDirectoryAtPath_error_ (oder einfach os.listdir ) an is_hidden .

Wenn Sie ohne pyobjc können Sie auf die Seite CoreFoundation Äquivalente, und verwenden ctypes . Die wichtigsten Funktionen sind CFURLCopyResourcePropertyForKey para is_hidden y CFURLEnumeratorCreateForDirectoryURL zum Auflisten eines Verzeichnisses.

Siehe http://pastebin.com/aCUwTumB für eine Implementierung.

Ich habe mit getestet:

  • 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

Es funktioniert in jeder Hinsicht (z. B. überspringt es ~/Library auf 10.8, zeigt es aber auf 10.6).

Es debe funktioniert auf jedem OS X 10.6+ und jedem Python 2.6+. Wenn Sie OS X 10.5 benötigen, müssen Sie die alten APIs verwenden (oder os.listdir ) und Filter auf is_hidden . Wenn Sie Python 2.5 benötigen, ändern Sie die bytes Schecks an str Checks (was natürlich in 3.x nicht funktioniert) und die with zu einem hässlichen try / finally oder manuelle Auslösung.

Wenn jemand vorhat, diesen Code in eine Bibliothek einzubauen, würde ich dringend empfehlen, sich nach pyobjc zuerst ( import Foundation und, falls Sie keine Antwort erhalten ImportError Sie gewinnen), und nur mit der ctypes Code, wenn er nicht verfügbar ist.


Eine letzte Anmerkung:

Einige Leute, die nach dieser Antwort suchen, versuchen, ein Rad neu zu erfinden, das sie nicht brauchen.

Wenn man so etwas macht, baut man oft eine grafische Benutzeroberfläche und möchte z. B. einen Dateibrowser mit einer Option zum Ein- oder Ausblenden versteckter Dateien anzeigen. Viele der beliebten plattformübergreifenden GUI-Frameworks (Qt, wx, etc.) haben diese Unterstützung eingebaut. (Außerdem sind viele von ihnen Open Source, so dass Sie ihren Code lesen können, um zu sehen, wie sie es tun).

Das beantwortet vielleicht nicht Ihre Frage - z.B. könnte es sein, dass sie einfach ein "filter hidden files"-Flag an den plattformeigenen Dateibrowser-Dialog weitergeben, aber Sie versuchen, einen Dateibrowser im Konsolenmodus zu erstellen und können das nicht tun. Aber wenn dies der Fall ist, verwenden Sie es einfach.

2voto

Ali Afshar Punkte 39615

Wir behandeln dieses Thema in einem Projekt, das wir schreiben. Wir haben eine Reihe von verschiedenen "versteckten Dateiprüfungen", die bei einer Hauptprüfung registriert sind. Wir lassen jede Datei durch diese Prüfer laufen, um zu sehen, ob sie versteckt sein sollte oder nicht.

Diese Prüfer sind nicht nur für verschiedene Betriebssysteme usw., sondern wir fügen "ignorierte" Dateien in die Versionskontrolle ein, und optionale Benutzerüberschreibungen durch Glob oder reguläre Ausdrücke.

Es läuft im Wesentlichen auf das hinaus, was Sie getan haben, aber auf eine anpassbare, flexible und erweiterbare Weise.

Siehe Quellcode hier: https://bitbucket.org/aafshar/pida-main/src/tip/pida/services/filemanager/filemanager.py

0voto

Jason R. Coombs Punkte 38667

Unter Einbeziehung meiner vorherigen Antwort und der von @abarnert habe ich Folgendes veröffentlicht jaraco.path 1.1 mit plattformübergreifender Unterstützung für die Erkennung versteckter Dateien. Wenn dieses Paket installiert ist, können Sie den versteckten Status einer beliebigen Datei erkennen, indem Sie einfach Folgendes aufrufen is_hidden :

from jaraco import path
path.is_hidden(file)

-5voto

S.Lott Punkte 371691

"Gibt es eine Standardmethode, um damit umzugehen?" Ja. Verwenden Sie ein standardisiertes (d.h. POSIX-kompatibles) Betriebssystem.

Da Windows nicht standardisiert ist, gibt es auch keinen anwendbaren Standard. Wäre es nicht toll, wenn es einen gäbe? Ich fühle Ihren Schmerz.

Alles, was Sie versuchen, plattformübergreifend zu tun, wird Win32-Krankheiten haben.

Ihre Lösung ist - für den derzeitigen Stand der Dinge - ausgezeichnet. Irgendwann in der Zukunft wird sich Microsoft vielleicht dafür entscheiden, ein POSIX-kompatibles Betriebssystem zu schreiben. Bis dahin kommen Sie gut mit der Situation zurecht.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X