Tags: PowerShell, Dateisystem
Unter dem alten Kommandointerpreter cmd.exe kann man mit dem dir-Befehl und dem Dienstprogramm attrib.exe die Attribute von Dateien recht unkompliziert ausgeben, filtern oder ändern. PowerShell hat dafür eigene Mechanismen, die aber etwas aufwändiger sind und sich daher primär für Scripts eignen.
Zu den gängigsten Aufgaben in Zusammenhang mit File-Attributen zählt das Filtern von Dateien anhand der Eigenschaften Archiv, Nur-Lesen, System oder Versteckt. Obwohl Windows auf NTFS-Partitionen eine ganze Reihe von Dateiattributen kennt, sind es meistens diese vier, welche man setzen oder entfernen möchte.
Die gesamte Liste an unterstützten Attributen kann man sich mit
[enum]::GetValues([system.io.fileattributes])
ausgeben lassen. Diese Namen braucht man nachher, wenn man die Attribute ändern möchte.
Nicht alle dieser Eigenschaften lassen sich schreiben, das gilt beispielsweise für Directory.
Attribute mit Get-ChildItem anzeigen
Während der dir-Befehl unter cmd.exe die Attribute von Dateien nicht anzeigt, scheinen diese beim PowerShell-Gegenstück Get-ChildItem (Alias gci oder dir) in der Ausgabe unter der Spalte Mode auf. Es beschränkt sich dabei jedoch auf die vier oben genannten plus das Verzeichnisattribut.
Dafür macht es der alte dir-Befehl sehr einfach, Dateien nach Attributen zu filtern. Ein
dir /ars
listet alle Dateien mit den Attributen Readonly und System auf. Für diese Aufgabe muss man unter PowerShell mehr Aufwand betreiben.
Zum einen sollte man Get-ChildItem mit dem Schalter -Force aufrufen, um sicherzustellen, dass auch jene Dateien angezeigt werden, die als Hidden oder System gesetzt wurden. Zum anderen muss man die Ausgabe durch einen Filter mit Where-Object (Alias ?) schicken:
dir -Force | ? mode -like *r*
Für das Prüfen des bloßen Schreibschutzes steht zudem eine separate Eigenschaft namens IsReadOnly zur Verfügung. Folgender Befehl würde True zurückgeben, wenn das Attribut ReadOnly gesetzt ist:
(dir -Force .\test.txt).IsReadOnly
Will man dieses Verfahren auf mehrere Dateien anwenden, dann könnte man dies so tun:
(dir -Force *.txt) | select Name, IsReadOnly
Filter für mehrere Attribute
Komplizierter wird es, wenn man nicht nur nach ReadOnly, sondern nach mehreren Attributen gleichzeitig fragen möchte. Hier müsste man alle möglichen Kombinationen aus Attributkürzel und Bindestrichen mit dem like-Operator untersuchen, zum Beispiel "*a--s" für Archive und ReadOnly.
Will man alle Dateien finden, die zum Beispiel das Attribut Hidden oder System gesetzt haben, dann bietet sich der Einsatz von -Match und einem regulären Ausdruck an:
dir -Force | ? mode -match '(r|h)'
Attributes-Eigenschaft nutzen
Die Abfrage der Eigenschaft Mode hat nicht nur den Nachteil, dass man die Zeichenkette aus den Anfangsbuchstaben der Attributnamen untersuchen muss, sondern dass sie wie erwähnt nur 5 Attribute berücksichtigt.
Daher kann man alternativ auf die Eigenschaft Attributes zurückgreifen:
dir -Force *.txt | Format-Table -AutoSize Name, Attributes
Dieser Befehl gibt den vollständigen Namen der Attribute aus, und der folgende zeigt alle versteckten Dateien mit der Endung .txt an:
gci -Force *.txt | ? Attributes -like "*Hidden*"
Zudem kann man darauf Filter anwenden, ohne sich um die Reihenfolge der Attribute kümmern zu müssen, wie das beim Zugriff auf die Zeichenkette Mode der Fall ist:
dir -Force *.txt | ?{$_.Attributes -like "*Hid*" -and $_.Attributes -like "*Read*"}
Da der Filter einen Ausdruck mit zwei Bedingungen enthält, lässt sich die vereinfachte Notation für Where-Object nicht mehr verwenden. Vielmehr muss man den Ausdruck in geschweifte Klammern setzen und auf die Variable $_ zurückgreifen. Im Vergleich zu einem herkömmlichen
dir /arh *.txt
ist die PowerShell-Version schon sehr komplex und für den Einsatz in einer interaktiven Shell eigentlich zu umständlich. Allerdings lassen sich damit alle Attribute abfragen, nicht nur die gängigen fünf.
Ein weiteres Cmdlet, das Dateiattribute ausgeben kann, ist Get-ItemProperty:
Get-ItemProperty *.txt | ft -Auto -Property Name, Attributes
Der Nachteil dieses Kommandos besteht aber darin, dass es keine Dateien berücksichtigt, bei denen die Attribute System oder Hidden gesetzt sind.
Dateiattribute ändern
Um die Attribute von Dateien zu bearbeiten, weist man der Attributes-Eigenschaft ein Array zu, bestehend aus den Attributnamen:
(dir -Force .\test.txt).Attributes = "Archive", "NotContentIndexed", "System"
Wie man hier sieht, muss man jedes Mal sämtliche Attribute zuweisen. Es ist nicht möglich, einfach nach dem Muster von
attrib +r test.txt
etwa ein einzelnes Attribut zu den bestehenden hinzuzufügen.
Mehrere Dateien ändern
Noch umständlicher wird dieses Verfahren, wenn man die Attribute mehrerer Files ändern möchte. Dann müsste man über alle Dateien mit einer Schleife iterieren (% als Alias für foreach):
dir -Force *.txt | %{$_.Attributes = "Hidden, ReadOnly"}
Eine Alternative stellt hier das Cmdlet Set-ItemProperty dar, das die Attribute mehrerer Dateien auf einmal setzen kann:
Set-ItemProperty *.txt -Name Attributes -Value "System, Archive"
Allerdings leidet es wie sein Gegenspieler Get-ItemProperty unter der Einschränkung, dass es keine Dateien ändern kann, die als System oder als versteckt markiert sind.
Täglich Know-how für IT-Pros mit unserem Newsletter
Verwandte Beiträge
Weitere Links
2 Kommentare
Kann es sein das hier "Dir" Anstatt Set-item bzw. Get-item benutzt wurde (versehentlich?)
"Dir" ist ein vordefiniertes Alias für Get-ChildItem. Für das CLI ok, aber für Scripts sollte man Aliase vermeiden.