Benutzer mit den meisten Antworten
Auswerten vom Ergebnis Get-Content -en byte -ReadCount 5 -TotalCount 5

Frage
-
Hallo,
ich habe mir eine Abfrage zusammengebaut mit der ich prüfen möchte ob die ersten 5 Zeichen in einer Datei den Wert null haben.
Hier meine ganze Abfrage:powershell.exe for ($i=2000; $i -le 2020; $i++) {Get-ChildItem -Path C:\Verteichnis\$i* -include *-* -rec -force | Get-Content -en byte -ReadCount 5 -TotalCount 5 | where {$_ -eq 0 } | Get-ChildItem | select fullname | out-file -filepath Mail.txt -append}
Es geht aber eigentlich nur um den Teil
"Get-Content -en byte -ReadCount 5 -TotalCount 5 | where {$_ -eq 0 } | Get-ChildItem | select fullname"
Wenn das erste und dritte Zeichen eine nul sind bekomme ich den Dateinamen zweimal zurückgegeben.
Wenn die ersten fünf stellen null sind bekomme ich fünf mal den Dateinamen zurückgegeben.
Ich möchte aber das ich den Dateinamen nur zurückbekommen, wenn die ersten 5 Zeichen Pro Datei alle nul sind.
Wie muss ich den Befehl umstellen?
Antworten
-
Du musst natürlich die summe der ersten 5 Bytes berechnen. Wenn die Summe = 0 ist sind alle 5 Bytes 0!
Berechnungen kann man innerhalb der Pipeline nur machen wenn man den Scriptblock vom ForEach-Object Cmdlet dazu benutzt.
In dem Scriptblock von dem ForEach-Object Cmdlet ist dann ein Script.
Da die Befehle hier alle in einer Zeile stehen, muss man diese Befehle mit dem Semikolon Trennen damit PowerShell die Befehle als "einzelne Zeilen" abarbeitet.
Mit dem Semikolon trennt man also einzelne Befehle, wenn Sie in einer Zeile stehen sollen.Da du das anscheinend als PowerShell.exe Einzeiler haben möchtest hier die "Einzeiler" Lösung (Ungetestet):
powershell.exe -Command "& { & {for ($i=2000; $i -le 2020; $i++) {Get-ChildItem -Path C:\Verteichnis\$i* -include *-* -rec -force | ForEach-Object { $Path = $_.Fullname; ; $Sum = Invoke-Expression ((Get-Content -Path $Path -Encoding byte -ReadCount 5 -TotalCount 5) -join '+'); If($Sum -eq 0){ $Path} }}} | Out-File Mail.txt -append}"
PowerShell Artikel, Buchtipps und kostenlose PowerShell Tutorials + E-Books
auf der deutschsprachigen PowerShell Community
Mein 21 Teiliger PowerShell Video Grundlehrgang
Deutsche PowerShell Videos auf Youtube
Folge mir auf:
Twitter | Facebook | Google+- Als Antwort markiert Alex Pitulice Mittwoch, 23. April 2014 14:56
-
Hätte ich gewusst das du das an 4mil Dateien machen musst hätte ich dir einen anderen Code gegeben.
Get-Content ist sehr langsam....
Invoke-Expression macht das noch langsamer (hier muss immer ein Text in Code umgesetzt werden)....
Hier ein Code der das ganze VIEL, VIEL schneller tun sollte:
# Ein Array erstellen mit allen Datei-Pfaden $Files = Get-ChildItem d:\temp -Filter *.txt | Select-Object -ExpandProperty Fullname # Jede Datei einzeln besuchen ForEach($File in $Files) { # FileStream erstellen $FileStream = [System.IO.File]::OpenRead($File) # Buffer für das Ergebnis bereitstellen $Bytes = [Byte[]]@(1,2,3,4,5) # 5 Bytes vom Anfang der Datei in den Buffer einlesen $FileStream.Read($Bytes,0,5) # Datei sofort wieder schliessen (wichtg!) $FileStream.Close() # Summe der Bytes bilden $Sum = 0 # jedes Byte auf die Summe aufaddieren ForEach($Byte in $Bytes) { $Sum += $Byte } # wenn die summe der Bytes 0 ist dann waren alle B5 Bytes 0 If($Sum -eq 0) { # ausgabe des Datei-Pfades $File } }
Dieser Code ist auf Geschwindigkeit Optimiert.
Da alle 4mil Dateinamen in den Speicher geladen werden, braucht der Code ein bisschen mehr RAM Speicherplatz!Siehe meinen Artikel :
PowerShell ForEach und ForEach-Object
http://www.admin-source.de/BlogDeu/905/powershell-foreach-und-foreach-object
PowerShell Artikel, Buchtipps und kostenlose PowerShell Tutorials + E-Books
auf der deutschsprachigen PowerShell Community
Mein 21 Teiliger PowerShell Video Grundlehrgang
Deutsche PowerShell Videos auf Youtube
Folge mir auf:
Twitter | Facebook | Google+- Bearbeitet Peter Kriegel Mittwoch, 16. April 2014 06:01
- Als Antwort markiert Alex Pitulice Mittwoch, 23. April 2014 14:56
-
param( [Parameter(Mandatory=$True,Position=1)] [string]$Quelle, [Parameter(Mandatory=$True,Position=2)] [string]$Logausgabe ) write-Host Das Verzeichnis und Unterverzecihnisse werden geprüft: $Quelle write-Host $LogAusgabe Get-ChildItem $Quelle -Filter *-* -rec | ForEach-Object { $Path = $_.Fullname $Sum = Invoke-Expression ((Get-Content -Path $Path -Encoding byte -ReadCount 5 -TotalCount 5) -join '+') If($Sum -eq 0){ $Path |out-file -filepath $LogAusgabe -width 1000 -append } }
Ich habe das Script für meine Bedürfnisse verändert und getestet.
Danke
- Als Antwort markiert Alex Pitulice Mittwoch, 23. April 2014 14:56
Alle Antworten
-
Du musst natürlich die summe der ersten 5 Bytes berechnen. Wenn die Summe = 0 ist sind alle 5 Bytes 0!
Berechnungen kann man innerhalb der Pipeline nur machen wenn man den Scriptblock vom ForEach-Object Cmdlet dazu benutzt.
In dem Scriptblock von dem ForEach-Object Cmdlet ist dann ein Script.
Da die Befehle hier alle in einer Zeile stehen, muss man diese Befehle mit dem Semikolon Trennen damit PowerShell die Befehle als "einzelne Zeilen" abarbeitet.
Mit dem Semikolon trennt man also einzelne Befehle, wenn Sie in einer Zeile stehen sollen.Da du das anscheinend als PowerShell.exe Einzeiler haben möchtest hier die "Einzeiler" Lösung (Ungetestet):
powershell.exe -Command "& { & {for ($i=2000; $i -le 2020; $i++) {Get-ChildItem -Path C:\Verteichnis\$i* -include *-* -rec -force | ForEach-Object { $Path = $_.Fullname; ; $Sum = Invoke-Expression ((Get-Content -Path $Path -Encoding byte -ReadCount 5 -TotalCount 5) -join '+'); If($Sum -eq 0){ $Path} }}} | Out-File Mail.txt -append}"
PowerShell Artikel, Buchtipps und kostenlose PowerShell Tutorials + E-Books
auf der deutschsprachigen PowerShell Community
Mein 21 Teiliger PowerShell Video Grundlehrgang
Deutsche PowerShell Videos auf Youtube
Folge mir auf:
Twitter | Facebook | Google+- Als Antwort markiert Alex Pitulice Mittwoch, 23. April 2014 14:56
-
Diese Datei sollte er finden:
Diese nicht:Mein Script findet beide Dateien.
Dein Script findet keine Datei.
Ich brauche ein Script was nur die obere Datei findet.
Schade das man nicht zählen kann....
Kann man denn was in die Richtung bauen vergleiche pos. 2 wenn pos. 1 NUL ist?
Vielleicht gehe ich die Sache auch falsch an?
- Bearbeitet AJGes Freitag, 11. April 2014 15:18
-
Ich habe das eben nochmal mit anderen Dateien überprüft.
Der Code ist definitiv richtig! Da bin ich mir zu 99.9999999% sicher ;-)
Warum startest du den Code mit PowerShell.exe?
Bitte teste den Code mal als richtiges Script in der PowerShell ISE:
Get-ChildItem d:\temp -Filter *.txt | ForEach-Object { $Path = $_.Fullname $Sum = Invoke-Expression ((Get-Content -Path $Path -Encoding byte -ReadCount 5 -TotalCount 5) -join '+') If($Sum -eq 0){ $Path} }
Mit welchem Editor schaust du dir die Datei an um zu prüfen das die Datei mit 5*NUL beginnt?
Viellleicht hat die Datei noch einen BOM den wir nicht sehen?Siehe: http://de.wikipedia.org/wiki/Byte_Order_Mark
PowerShell Artikel, Buchtipps und kostenlose PowerShell Tutorials + E-Books
auf der deutschsprachigen PowerShell Community
Mein 21 Teiliger PowerShell Video Grundlehrgang
Deutsche PowerShell Videos auf Youtube
Folge mir auf:
Twitter | Facebook | Google+
- Bearbeitet Peter Kriegel Montag, 14. April 2014 05:47
-
Hätte ich gewusst das du das an 4mil Dateien machen musst hätte ich dir einen anderen Code gegeben.
Get-Content ist sehr langsam....
Invoke-Expression macht das noch langsamer (hier muss immer ein Text in Code umgesetzt werden)....
Hier ein Code der das ganze VIEL, VIEL schneller tun sollte:
# Ein Array erstellen mit allen Datei-Pfaden $Files = Get-ChildItem d:\temp -Filter *.txt | Select-Object -ExpandProperty Fullname # Jede Datei einzeln besuchen ForEach($File in $Files) { # FileStream erstellen $FileStream = [System.IO.File]::OpenRead($File) # Buffer für das Ergebnis bereitstellen $Bytes = [Byte[]]@(1,2,3,4,5) # 5 Bytes vom Anfang der Datei in den Buffer einlesen $FileStream.Read($Bytes,0,5) # Datei sofort wieder schliessen (wichtg!) $FileStream.Close() # Summe der Bytes bilden $Sum = 0 # jedes Byte auf die Summe aufaddieren ForEach($Byte in $Bytes) { $Sum += $Byte } # wenn die summe der Bytes 0 ist dann waren alle B5 Bytes 0 If($Sum -eq 0) { # ausgabe des Datei-Pfades $File } }
Dieser Code ist auf Geschwindigkeit Optimiert.
Da alle 4mil Dateinamen in den Speicher geladen werden, braucht der Code ein bisschen mehr RAM Speicherplatz!Siehe meinen Artikel :
PowerShell ForEach und ForEach-Object
http://www.admin-source.de/BlogDeu/905/powershell-foreach-und-foreach-object
PowerShell Artikel, Buchtipps und kostenlose PowerShell Tutorials + E-Books
auf der deutschsprachigen PowerShell Community
Mein 21 Teiliger PowerShell Video Grundlehrgang
Deutsche PowerShell Videos auf Youtube
Folge mir auf:
Twitter | Facebook | Google+- Bearbeitet Peter Kriegel Mittwoch, 16. April 2014 06:01
- Als Antwort markiert Alex Pitulice Mittwoch, 23. April 2014 14:56
-
param( [Parameter(Mandatory=$True,Position=1)] [string]$Quelle, [Parameter(Mandatory=$True,Position=2)] [string]$Logausgabe ) write-Host Das Verzeichnis und Unterverzecihnisse werden geprüft: $Quelle write-Host $LogAusgabe Get-ChildItem $Quelle -Filter *-* -rec | ForEach-Object { $Path = $_.Fullname $Sum = Invoke-Expression ((Get-Content -Path $Path -Encoding byte -ReadCount 5 -TotalCount 5) -join '+') If($Sum -eq 0){ $Path |out-file -filepath $LogAusgabe -width 1000 -append } }
Ich habe das Script für meine Bedürfnisse verändert und getestet.
Danke
- Als Antwort markiert Alex Pitulice Mittwoch, 23. April 2014 14:56
-
OK!
Wenn dein Problem erledigt ist dann lies bitte noch das hier:
Wozu Antworten markieren und für Beiträge abstimmen?
PowerShell Artikel, Buchtipps und kostenlose PowerShell Tutorials + E-Books
auf der deutschsprachigen PowerShell Community
Mein 21 Teiliger PowerShell Video Grundlehrgang
Deutsche PowerShell Videos auf Youtube
Folge mir auf:
Twitter | Facebook | Google+