Daten|teiler
Kopieren als Kulturtechnik

PowerShell-Workshop: Dateilisten erzeugen und auch drucken

22. September 2011 von Christian Imhorst

Das aktuelle Heft 04/2011 von Ubuntu User feiert eine Premiere: Im ersten Bash-Workshop erfährt man, wie man in der Konsole Dateien in einem Verzeichniss auflistet, zurechtschnitzt und ausdruckt. Bash-Skripte erstellen kann ich schon, ich will aber PowerShell lernen. Also habe ich den Workshop etwas abgewandelt.

Die Suche nach einem Editor mit integrierter Shell kann man bei der PowerShell etwas abkürzen, da man im Zielverzeichnis der Installation PowerShell ISE findet. Die drei Buchstaben stehen für Integrated Scripting Environment, eine grafische Benutzeroberfläche, mit der man im selben Fenster nicht nur Befehle, sondern auch Skripte ausführen, schreiben und bearbeiten kann. Ziel des Workshops ist es, eine Liste von MP3-Dateien ohne Dateiendung zu erzeugen. Um eine Dateiliste auszugeben gibt es dank der Aliase viele Möglichkeiten. So kann man wie in der Bash ls nehmen, oder auch dir. Dahinter verbirgt sich jedes Mal das Cmdlet get-childitem, kurz gci.

.

Wie man auf der Abbildung sieht, listet get-childitem mehr Parameter auf, als man vielleicht möchte. Ich will zum Beispiel nur den Namen und nicht die anderen drei Parameter Mode, LastWriteTime und Length. Um die anderen Parameter auszuschließen, braucht man nur den eingeben, den man möchte. In meinem Fall also:

gci -Name

Um die MP3-Endungen der Auflistung zu entfernen, wird im Workshop der Befehl sed benutzt, den es leider in einer Standard-Installation von Windows nicht gibt. Anstelle von sed und einem regulären Ausdruck verwende ich eine ForEach-Schleife mit dem Replace-Parameter, die durch eine Liste von Objekten geht und dabei jedes Objekt einzeln abarbeitet. Das jeweilige Objekt wird in der Schleife mit $_ angesprochen, ein Platzhalter in der aktuellen Pipeline. Eine Eigenschaft eines Objekts wird dann mit $_.NameDerEigenschaft angesprochen. Solche Platzhalter heißen Automatische Variable. Wer genau wissen möchte, welche Automatische Variable es in der PowerShell gibt, kann sich mit folgendem Befehl einen Überblick verschaffen:

get-help about_automatic_variables

Eine Auflistung der MP3-Dateien im Verzeichnis, aber ohne die Dateiendungen, sähe dann folgendermaßen aus:

gci -Name | foreach {$_ -replace ".mp3", ""} > titelliste.txt

Mit der Umleitung in die Textdatei titelliste.txt wird die Dateiliste nicht in die Konsole geschrieben, sondern gleich in die Textdatei hinein, die für die CD-Hülle ausgedruckt werden soll. Führt man den Befehl ein zweites Mal aus, stößt man allerdings auf ein Problem: In der Textdatei stehen nicht nur die Titel, sondern auch der Name der Textdatei, weil die sich nun ebenfalls im Verzeichnis befindet. Damit sie nicht angezeigt wird, kann man alle Dateien mit der Endung TXT von der Liste ausschließen.

gci -Name -Exclude *.txt | foreach {$_ -replace ".mp3", ""} > titelliste.txt

Ich möchte auch gerne überprüfen, welche Infos in die Textdatei geschrieben werden und zur Kontrolle die Dateien zusätzlich auch noch in der Konsole ausgeben. Im Workshop von Ubuntu User wird dazu der Befehl tee benutzt, der wie ein T-Stück die Ausgabe in zwei Richtungen lenkt. Das Commandlet Tee-Object bewirkt in der PowerShell dasselbe und die Kurzform ist wie in der Bash tee. Das vollständige Kommando zur Ausgabe des Verzeichnisses mit den MP3-Dateien auf der Konsole und in eine Textdatei sieht dann so aus:

gci -Name -Exclude *.txt | foreach {$_ -replace ".mp3", ""} | tee titlliste.txt
01 sad robot
02 take me to the bonuslevel because i need an extralife
03 lemmings in love
04 space invaders
05 i want to be a machine
06 1_2 player game
07 game over
08 rock'n'roll hall of fame

Den Inhalt der Textdatei kann man dann auch ausdrucken, falls man schnell mal ein CD-Cover mit den Songs drauf braucht. Dazu muss man aber erstmal wissen, welche Drucker am Rechner überhaupt angeschlossen sind. In der Bash klappt das mit dem Befehl lpstat -a, in der PowerShell benötigt man dazu ein WMI-Objekt wie win32_printer.
Das Cmdlet für die WMI-Objekte heißt Get-WmiObject oder kurz gwmi. Mit der Umleitung in das Select-Objekt wird dann nur der Name des Druckers angezeigt:

gwmi win32_printer | select name
 
name
----
Brother HL-2030 series
Microsoft XPS Document Writer

Wenn man den Drucker weiß, kann man den Inhalt der Textdatei zum Drucker umleiten, wofür in der Bash der Befehl lp zuständig ist:

Get-Content titlliste.txt | Out-Printer -name "Brother HL-2030 series"

Geschrieben in Powershell, Windows | Kommentare deaktiviert für PowerShell-Workshop: Dateilisten erzeugen und auch drucken

Wenn Anwendungen unter Windows nerven

9. September 2011 von Christian Imhorst

Wenn Anwendungen unter Windows Vista oder Windows 7 nerven, weil sie ständig nach dem Passwort eines Benutzers mit Administrationsrechten verlangen, dann liegt das an der Benutzerkontensteuerung oder auch User Account Control (UAC). Ganz schlimm fand ich es auf einem Netbook von Samsung. Wie es sich gehört, habe ich ein Benutzerkonto mit Administrationsrechten, nennen wir es Ruth, und ein einfaches Benutzerkonto für mich eingerichtet. Nach jedem Neustart und Einloggen verlangten 5 Anwendungen von Samsung Ruths Passwort, was sehr anstrengend sein kann.

Windows selbst bietet keine Bordmittel, um einzelne Anwendungen von der Benutzerkontensteuerung herauszunehmen. Man kann zwar Anwendungen über die Aufgabenplanung mit höheren Privilegien starten, aber nur über eine Verknüpfung. Das fand ich für diesen Fall zu fummelig. In den „Eigenschaften“ der einzelnen Anwendung kann man zwar die Option „Programm als Administrator ausführen“ setzen, was aber nur funktioniert, wenn man die Benutzerkontensteuerung deaktiviert hat, wovon abzuraten ist.

Letztendlich habe ich das Tool Microsoft Application Compatibility Toolkit installiert, um die UAC für bestimmte Anwendungen zu deaktivieren. Ich habe dazu zwei Anleitungen gefunden, die beide behaupten, man könne beim Compatibility Administrator den Punkt „Als Administrator ausführen“ mittels rechter Maustaste aus dem Startmenü anklicken. Bei mir ging es seltsamerweise nicht. Es klappt aber, wenn ich im Ordner „C:\Program Files\Microsoft Application Compatibility Toolkit\Compatibility Administrator“ mit der rechten Maustaste auf die Anwendung klicke, um sie mit Administrationsrechten zu starten. So wie in der Anleitung beschrieben konnte ich dann die folgenden Anwendungen aus der Benutzerkontensteuerung heraus nehmen:

  • C:\Program Files\Samsung\BatteryLifeExtender\BatteryLifeExtender.exe
  • C:\Program Files\Samsung\BatteryLifeExtender\StartUpSetup.exe
  • C:\Program Files\Samsung\Samsung Update Plus\SUPBackground.exe
  • C:\Program Files\Samsung\EasySpeedUpManager\EasySpeedUpManager2.exe
  • C:\Program Files\Samsung\SamsungFastStart\SmartRestarter.exe

Geschrieben in Windows | Kommentare deaktiviert für Wenn Anwendungen unter Windows nerven

„I don’t like spam“, oder wie man einen Mailserver testet

5. September 2011 von Christian Imhorst

Dieser Artikel erschien erstmals in freiesMagazin 09/11: Es begann mit einem Irrtum. Im Werbebrief vom Google für den AdWords-Dienst befand sich ein Gutschein über 75 Euro, der auf einen völlig fremden Menschen ausgestellt war. Wenn man Sandra Fründt, Head of Business Marketing Google Deutschland, auf ihren Fehler aufmerksam machen will, immerhin hat sie diesen Brief unterschrieben, stößt man auf ein Problem: Im Schreiben ist überhaupt keine E-Mail-Adresse angegeben. Das Unternehmen, das mit Suchmaschine und E-Mail-Dienst im Internet groß geworden ist, zeigt sich in seiner Werbung ganz schön verschlossen.

Den restlichen Eintrag lesen »

Geschrieben in Gnu/Linux | Kommentare deaktiviert für „I don’t like spam“, oder wie man einen Mailserver testet

Windows-Programme mit Python steuern

4. September 2011 von Christian Imhorst

Im Blog Der Bayer und der Würschtlmann bin ich auf den Beitrag Windows-(GUI-)Programme mit Python fernsteuern von Sebastian gestoßen. Für die Automatisierung der Windows-Programme benutzt er pywinauto, das einen sehr interessanten Eindruck macht, aber leider etwas durch die Abwesenheit von Dokumentation glänzt. Trotzdem soll man laut Sebastian schnell zu guten Ergebnissen kommen. Pywinauto ist sicherlich ein Vesuch wert, weil es objektorientierter und pythonmäßiger sein soll. Wenn man sich aber schon etwas mit dem Windows Script Host (WSH) oder dem Component Object Model (COM) auskennt, liegt einem Win32com vielleicht mehr.

Um überhaupt etwas mit Pywinauto oder Win32com zu machen, muss man Python unter Windows installiert haben. Ich habe mich zum Beispiel für Python 3.2 entschieden. Alternativ gibt es auch noch die Communuty Edition von ActivePython, das schon extra Module wie Win32com mitbringt. Beim original Python muss man auf jeden Fall noch die Erweiterung Pywin32 herunterladen, wenn man das Modul Win32com nutzen möchte. Allerdings kann es passieren, dass der erste Versuch, das Modul zu importieren, auf einen Fehler hinaus läuft:

>>> import win32com.client 
Traceback (most recent call last):
File "D:\EQ\InventoryDumps\testScript1.py", line 1, in <module>
import win32com.client as win32
File "D:\Python32\lib\site-packages\win32com\__init__.py", line 5, in <module>
import win32api, sys, os
ImportError: DLL load failed: The specified module could not be found.

Ist das der Fall, kann man das Problem mit folgendem Befehl beheben:

C:\Python32\Scripts\pywin32_postinstall.py

Wenn die Installation erfolgreich ist, steht einem die Welt der Windows-Objekte wie COM oder WSH mehr oder weniger offen. So kann man mit COM Anwendungen aus dem Microsoft Office-Paket oder den Internet Explorer automatisieren. COM dient dabei zur Interprozesskommunikation und dynamische Objekterzeugung unter Windows. Bevor man die Funktionen von COM-Objekten nutzen kann, muss man sie instanzieren, wofür die COM-Komponenten Schnittstellen anbieten. Im folgenden Beispiel wird eine Instanz des Internet Explorers durch die Angabe seiner ProgID („InternetExplorer.Application“) erzeugt:

import win32com.client
ie = win32com.client.Dispatch("InternetExplorer.Application")
ie.Visible = 1
ie.Navigate("http://www.datenteiler.de")
ie.GoHome()
ie.quit()

Nach der Instanzierung steht ein Internet Explorer bereit, der allerdings noch nicht zu sehen ist, außer als Prozess im Taskmanager oder mit dem Cmdlet Get-Process in der PowerShell. Der Prozess ist unabhängig vom Python-Interpreter. Wird die Konsole geschlossen, bleibt der Prozess erhalten und aktiv. Erst wenn man der Eigenschaft von Visible auf wahr setzt, wird diese Instanz des Internet Explorers sichtbar.
Wenn man sich mit dem Einsatz von COM-Anwendungen in der PowerShell auskennt, kommt einem der Quelltext doch bekannt vor:

$ie = New-Object -ComObject InternetExplorer.Application
$ie.Visible = $true
$ie.Navigate("http://www.datenteiler.de")
$ie.GoHome()
$ie.Quit()

Das folgende SendKey-Beispiel mit dem WSH kann auch zu einem Déjà-vu führen, wenn man den Python-Quelltext mit dem VBScript-Code vergleicht. Erstmal das Beispiel um Tastendrücke zu simulieren in Python:

import win32api
import win32com.client
shell = win32com.client.Dispatch("WScript.Shell")
shell.Run("Notepad") 
win32api.Sleep(1500) 
shell.AppActivate("Notepad") 
win32api.Sleep(1500) 
shell.SendKeys("Hallo Welt!{ENTER}") 
shell.SendKeys("^s")
shell.SendKeys("{ENTER}")
win32api.Sleep(1500)
shell.SendKeys("Hallo.txt{ENTER}")

Das Äquivalent in VBScript sieht dann so aus:

' SendkeyBeispiel.vbs
Option Explicit
Dim objWScriptShell
Set objWScriptShell = CreateObject("WScript.Shell")
objWScriptShell.Run "notepad"
Wscript.Sleep 1500 ' Warte bis Notepad fertig ist
objWScriptShell.SendKeys "Hallo Welt!{ENTER}"
objWScriptShell.SendKeys "^s"
objWScriptShell.SendKeys "{ENTER}"
Wscript.Sleep 1500
objWScriptShell.SendKeys "Hallo.txt{ENTER}"
WScript.Quit

Man kann mit dem Win32Com-Modul in Python noch einiges mehr anfangen, zum Beispiel die Maus positionieren und Mausklicks senden. Damit sind die Möglichkeiten von Python im Component Object Model oder des Windows Script Host bei weitem noch nicht ausgeschöpft.

Geschrieben in Python, Windows | Kommentare deaktiviert für Windows-Programme mit Python steuern

Tanz den Bubblesort

29. August 2011 von Christian Imhorst

Endlich habe ich mal verstanden, wie der Bubblesort funktioniert! Nicht schlecht was die Jungs und Mädels dort Vortanzen. Hier zum Beispiel der Tanz in Python implementiert, allerdings nur mit dem unsortierten Anfang, dem sortierten Ende und ohne das Ganze im Mittelteil:

# Bubblesort in Python
 
def bubblesort(a):
    for j in range(len(a) - 1):
        for i in range(len(a) - j - 1):
            if a[i] > a[i+1]:
                tmp = a[i]
                a[i] = a[i+1]
                a[i+1] = tmp
    return a
 
a = [3, 0, 1, 8, 7, 2, 5, 4, 6, 9]
print("Unsortiert: ", a)
 
result = bubblesort(a)	
print("Sortiert  : ", result)

Ich hoffe nur, dass ich die Musik auch wieder aus meinem Kopf bekomme. ;-)

[via zipfelmaus.com]

Geschrieben in Programmieren, Python | Kommentare deaktiviert für Tanz den Bubblesort

Steganografie für Anfänger

22. August 2011 von Christian Imhorst

Für die August-Ausgabe der Hakin9 habe ich meinen alten Blog-Post Steganografie für Anfänger „recycelt“. Der neue Artikel ist etwas anders strukturiert und um Befehle für die PowerShell erweitert worden:

Steganografie kommt aus dem Griechischen und heißt “geheimes Schreiben”. Herodot berichtet, dass einem Sklaven der Kopf geschoren wurde, um die Nachricht auf seine Kopfhaut zu tätowieren. Als das Haar wieder nachgewachsen war, wurde er zum Empfänger der geheimen Nachricht geschickt, der den Kopf des Sklaven wieder rasierte, um sie lesen zu können. Die Haare haben also die eigentliche Nachricht verdeckt. Ähnlich funktioniert Steganografie noch 2500 Jahre danach. Steganografie ist die Kunst, Information zu tarnen, um sie verborgen zu übermitteln. Ihr Zweck ist also, geheime Information mithilfe anderer unverfänglicher Information so zu verbergen, dass sie von einem unbedarften Beobachter, Mensch oder Maschine, nicht erkannt wird. Eine geheime Nachricht wird dabei in einer anderen Nachricht, zum Beispiel in einer Bilddatei versteckt. Dem Empfänger muss natürlich bekannt sein, dass das Bild eine geheime Nachricht enthält, so wie dem Empfänger in der Antike klar sein musste, dass sich die Nachricht unter dem Haar des Sklaven befand. Wenn das Originalbild fehlt, ist es sehr schwierig herauszufinden, ob ein Bild eine Geheimbotschaft versteckt. Die meisten Steganogramme werden enttarnt, wenn sie mit der Originaldatei verglichen werden und sich daraus Abweichungen ergeben. Wenn das Original gelöscht und ein gutes Bild mit vielen Unschärfen, hoher Pixelzahl und wenig Kanten gewählt wurde, dann ist im Prinzip nicht mehr festzustellen, ob eine Bilddatei ein Steganogramm ist.

Den restlichen Eintrag lesen »

Geschrieben in Publikationen | Kommentare deaktiviert für Steganografie für Anfänger

Wie kann man prüfen, ob eine E-Mail-Adresse nicht existiert, ohne eine E-Mail zum Testen zu verschicken?

13. August 2011 von Christian Imhorst

Vielleicht kennt ihr das Problem ja auch: Man hat vom Format her eine korrekte E-Mail-Adresse, trotzdem wird sie nicht zugestellt, weil das Ziel dem Mail-Server unbekannt ist. Eine formal richtige E-Mail-Adresse wäre zum Beispiel lpage@google.com. Sollte ich aber an diese Adresse eine E-Mail schicken, würde ich folgende Antwort erhalten:

Delivery to the following recipient failed permanently:
 
     lpage@google.com
 
Technical details of permanent failure: 
Google tried to deliver your message, but it was rejected by the recipient domain. We recommend contacting the other email provider for further information about the cause of this error. The error that the other server returned was: 550 550-5.1.1 The email account that you tried to reach does not exist. Please try
550-5.1.1 double-checking the recipient's email address for typos or
550-5.1.1 unnecessary spaces. Learn more at                             
550 5.1.1 http://mail.google.com/support/bin/answer.py?answer=6596 c20si4840621fai.47 (state 14).

Den restlichen Eintrag lesen »

Geschrieben in Gnu/Linux, MacOS X und iPhone, Windows | Kommentare deaktiviert für Wie kann man prüfen, ob eine E-Mail-Adresse nicht existiert, ohne eine E-Mail zum Testen zu verschicken?

Gurus AI auf Google+

11. August 2011 von Christian Imhorst

Ich kann mir schon vorstellen, dass es ein paar Leute gibt, die über Google+ genauso denken wie Katja Kullmann in der FAZ: „Bei Google+ ist niemand außer Sascha Lobo. Es ist wirklich schrecklich einsam dort.“ Man kann aber auf keinen Fall auch nur ein bisschen ein Nerd sein, wenn man diesen Gedanken ansatzweise teilt. Denn für Nerds und Geeks wie mich ist Google+ eine kleine Fundgrube: Als Geek habe ich natürlich um Wil Wheaton und Sheldon Cooper einen Kreis gezogen. Beide in einem Kreis zu haben ist einfach klasse, und ich gehe jede Wette ein, dass Wil Wheaton auch bei Google+ wieder sich selbst spielt.

Als Nerd habe ich den Kreis „Gurus of the Information Age“ oder kurz „Gurus AI“ natürlich um Leute wie Linus Torvalds, Tim O’Reilly, Larry Page, Guido van Rossum, Steven Levy, Miguel de Icaza, Ted Ts’o, Sergey Brin, Eric Raymond und Jon „maddog“ Hall gezogen. Ich weiß nicht, habe ich noch wen vergessen?

Geschrieben in Allgemein | Kommentare deaktiviert für Gurus AI auf Google+

Kleiner Stolperstein bei Funktionen in der PowerShell

9. August 2011 von Christian Imhorst

Bei der Definition von Funktionen in der PowerShell gibt es einen kleinen Stolperstein, den man kennen sollte, wenn man nicht stürzen — oder besser — keine falschen Ergebnisse haben will. Gegeben ist zum Beispiel die kleine Funktion Add-Together():

# Add-Together.ps1
 
function Add-Together([string]$text,[int]$zahl1,[int]$zahl2)
    {
    Write-Host $text ($summe = $zahl1 + $zahl2)
    }

Jetzt könnte man meinen, dass die Funktion Add-Together() genauso eingesetzt wird, wie sie definiert wurde, also mit Klammern, einem Text-String und zwei Integer-Zahlen, die durch zwei Kommas voneinander getrennt werden:

Add-Together("Das Ergebnis ist", 4, 5)

In der Konsole ausgegeben wird aber Das Ergebnis ist 4 5 0, da die PowerShell Add-Together() in dieser Schreibweise nicht als Funktion ansieht, sondern als Array.

Ein Array wird in der PowerShell erstellt, indem eine kommaseparierte Liste mit Werten an eine Variable übergeben wird, was im kurzen Tutorial „Programmieren mit der Windows PowerShell“ von Nils Gutsche sehr schön prägnant beschrieben ist. Für die Funktion bedeutet das, dass der erste Wert das Array ist und die beiden anderen leer bleiben, also 0 sind. Daher die Ausgabe Das Ergebnis ist 4 5 0 in der Konsole.

In der PowerShell werden die Parameter einer Funktion ohne Klammern und ohne trennende Kommas übergeben, so dass der vollständige Code dann folgendermaßen aussieht:

# Add-Together.ps1
 
function Add-Together([string]$text,[int]$zahl1,[int]$zahl2)
    {
    Write-Host $text ($summe = $zahl1 + $zahl2)
    } 
Add-Together "Das Ergebnis ist" 4 5

Geschrieben in Powershell, Windows | Kommentare deaktiviert für Kleiner Stolperstein bei Funktionen in der PowerShell

Suchen und auflisten in der PowerShell

14. Juli 2011 von Christian Imhorst

In der Windows-Befehlszeile cmd.exe oder in DOS hat man zum Auflisten von Dateien den DIR-Befehl benutzt. Der Befehl klappt in der PowerShell auch noch, ist allerdings ein Alias zum Cmdlet Get-Childitem.
Wenn man den Befehl DIR nicht mehr benutzen möchte, Get-Childitem aber zu lang findet, kann man auch den Alias gci nehmen, oder auch ls, wenn man mehr an Shells wie die Bash gewöhnt ist. Eine Einschränkung hat die Geschichte mit den Aliasen allerdings: Parameter zu den Befehlen kann man nicht so einfach in die PowerShell übertragen. Der Befehl dir /s klappt nicht, stattdessen muss man den Parameter -recurse nehmen, wenn man Unterordner in die Auflistung mit einbeziehen will.

PS C:\Users\Christian> dir -recurse
 
    Verzeichnis: C:\Users\Christian
 
Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d-r--        28.05.2011     15:56            Contacts
d-r--        27.06.2011     11:37            Desktop
d-r--        05.06.2011     22:49            Documents
d-r--        12.07.2011     21:20            Downloads
[...]

Wie sucht man nun in der PowerShell? Der Befehl Get-ChildItem C:\ listet einfach alle Dateien im Wurzelverzeichnis C: auf. Wie schon oben erwähnt, kann man mit dem Parameter -recurse auch Dateien in Unterordnern auflisten.
Dabei kann man auch nach bestimmten Dateien suchen. Der folgende Befehl listet zum Beispiel alle Dateien auf, auch die in den Unterordnern, die ein „python“ im Namen tragen:

gci -recurse | Where-Object {$_.Name -like "*python*"}

Man kann aber nicht nur nach Namen sortieren, sondern auch nach bestimmten Endungen:

gci  $env:windir -recurse | Where-Object {$_.Extension -eq ".dll"}

Leitet man die Ausgabe der Suche nach Format-Table oder Select-Object um, dann bekommt man sie schön vorsortiert:

PS C:\Users\Christian> gci  $env:windir -recurse `
>> | Where {$_.Extension -eq ".dll"} `
>> | Format-Table FullName, CreationTime, Length
>>
 
FullName                               CreationTime                 Length                                         
--------                               ------------                 ------                                                 
C:\Windows\RtlExUpd.dll                 15.11.2010 07:59:44         1251944                                                
C:\Windows\twain.dll                    10.06.2009 23:41:17           94784                                              
C:\Windows\twain_32.dll                 14.07.2009 02:14:33           51200  
C:\windows\assembly\GAC\Microsoft.In... 14.07.2009 06:42:34          356352
C:\windows\assembly\GAC\Microsoft.In... 14.07.2009 06:42:34          516096
C:\windows\assembly\GAC\Microsoft.In... 05.06.2011 22:27:52            6656
C:\windows\assembly\GAC\Microsoft.St... 05.06.2011 22:29:56           22552                                           
[...]

Hier ist allerdings ein kleiner Exkurs zur formatierten Ausgabe von Format-Table nötig: Wenn der Inhalt der Spalte breiter bzw. länger ist, als die Spalte selbst, dann wird der Inhalt abgeschnitten und der Rest durch drei Punkte dargestellt. Man kann also nicht wirklich erkennen, wie es in der Spalte weiter geht. Übergibt man die Ausgabe in eine Textdatei, in der die Spalten ja breiter sein könnten, da sie nicht durch die Konsole begrenzt wird, bekommt man dasselbe Ergebnis. Der AutoSize-Parameter von Format-Table hilft leider auch nicht weiter, weil er gerade mal nur so viele Spalten darstellt, wie sie in die Konsole passen. Alles was darüber hinaus geht, lässt er weg. Auch diese Spalten landen nicht in der Ausgabedatei. Die Lösung hier heißt Strings, da Strings nicht den selben Beschränkungen wie andere Objekte der PowerShell unterliegen:

PS C:\Users\Christian> gci $env:USERPROFILE -r `
>> | Where {($_.lastwritetime -gt "2011-06-20")} `
>> | Format-Table -Property * -AutoSize `
>> | Out-String -Width 4096 `
>> | Out-File $env:USERPROFILE\log.txt
>>

Lässt man das Cmdlet Out-File am Ende weg, um die Ausgabe direkt in das Terminal umzuleiten, sieht das Ergebnis auf Grund der Beschränkungen durch die Konsole sehr wüst aus. Die Text-Datei kann sich aber sehr gut sehen lassen.

Doch zurück zum eigentlichen Thema: Nun sieht Where-Object doch recht kompliziert aus. Anstatt die Ausgabe des Get-ChildItem-Befehls an ein Where-Objekt weiterzuleiten, stellt der Befehl selbst Parameter zur Sortierung bereit. Eine vereinfachte Schreibweise, in der statt -recurse einfach nur -r geschrieben wird, ist dann zum Beispiel:

Get-ChildItem -r -filter *.dll -path $env:windir

Ersetzt man -filter durch -exclude schließt man Dateien von der Suche aus. Davon abgesehen kann man auch die Parameter-Bezeichnungen wie -filter oder -path ganz weglassen:

gci -recurse $env:USERPROFILE *python*

Wann nützt aber eine Umleitung in ein Where-Objekt? Zum Beispiel dann, wenn man nur Dateien auflisten will, die eine bestimmte Größe überschreiten,

Get-ChildItem | Where-Object {$_.length -gt 4000}

oder Dateien, die nach einem bestimmten Datum erstellt worden sind, in diesem Fall nach dem 20.06.2011:

Get-ChildItem | Where-Object {($_.lastwritetime -gt "2011-06-20")}

Das sind beides wichtige Befehle, wenn man sich mal wieder fragt, warum der Fileserver innerhalb kürzester Zeit voll gelaufen ist, bzw. welche großen Dateien auf dem Server schon seit ewigen Zeiten nicht mehr angefasst worden sind. In diesem Zusammenhang habe ich im Blog von Christian Jäckle einen Befehl gefunden, der alle Dateien in einem Verzeichnis anzeigt, die in den letzten 15 Minuten bearbeitet wurden:

gci -r C:\ | Where-Object {$_.LastWriteTime -gt (Get-Date).AddMinutes(-15)} | export-csv $env:userprofile\Log.csv -notype

Mit dem Cmdlet Get-Date wird die aktuelle Zeit ermittelt, von der 15 Minuten abgezogen werden. Das Ergebnis wird in eine CSV-Datei im User-Verzeichnis geschrieben. Den Pfad zum User-Verzeichnis liefert die Umgebungsvariable userprofile, die der Ausdruck $env:userprofile liefert.
Welche Umgebungsvariablen es überhaupt gibt, liefert übrigens auch der Befehl Get-ChildItem:

Get-Childitem env:
 
Name                           Value
----                           -----
ALLUSERSPROFILE                C:\ProgramData
APPDATA                        C:\Users\Christian\AppData\Roaming
CommonProgramFiles             C:\Program Files\Common Files
COMPUTERNAME                   KDBSH4-PC
ComSpec                        C:\windows\system32\cmd.exe
[...]

Aber das ist noch nicht alles, was Get-ChildItem auflisten kann. Man kann auch Registry-Einträge anzeigen lassen, um sie anschließend eventuell zu bearbeiten. Der folgende Befehl listet die installierte Software des Rechners auf, zumindest diejenige, die auch in die Registry eingetragen wurde:

Get-ChildItem hklm:\software

Geschrieben in Powershell, Windows | Kommentare deaktiviert für Suchen und auflisten in der PowerShell

« Previous Entries Next Entries »