h41msh1c0r
Goto Top

Powershell Verzeichnisse vergleichen mit Zwischenschritt

Hi@All,

Ablauf:

1. Verzeichnis A (root: c:\temp\dir1) einlesen (pfad ab root, name, länge, letzte mal geschrieben) --> Ergebnis in txt file
2. Verzeichnis B (root: c:\temp\dir2) einlesen (pfad ab root, name, länge, letzte mal geschrieben) --> Ergebnis in txt file
3. Dateien Vergleichen --> Diff farbig ausgeben + Indicator

Problem:

Wenn ich über gci ein recurse durch das Verzeichnis laufe und das in ein out-file pipe bekomme ich zuviel an Ausgabe in der Datei.

Mit dem Zwischenpipe Block ist es weniger:

gci "<pfad>" -recurse |  %{$_.FullName} | Out-File "c:\temp\DIR1.txt"    

Wie bekomme ich es hin das dort statt dem FullName der Pfad und unterverzeichnisse beginnend ab dem dir1 oder dir2 in der Datei landet?

Man könnte mit -replace arbeiten, aber geht das auch eleganter?

Zum CompareObject im Schritt 3 gehts später, wenn die Dateien mit get-Content eingelesen wurden.

Gruß

Content-Key: 319023

Url: https://administrator.de/contentid/319023

Ausgedruckt am: 19.03.2024 um 04:03 Uhr

Mitglied: 131301
131301 25.10.2016 aktualisiert um 13:52:23 Uhr
Goto Top
Hi.
Wieso das Gedöns in Textdateien schreiben ?????
Das geht doch so ohne irgendwelche Zwischenschritte mit compare.
Powershell ist objektorientiert, da ist das Schreiben in eine Textdatei als Zwischenschritt nur kontraproduktiv.

Wenn man einzelne Eigenschaften ausgeben will hilft einem select -Expand <PROPERTY>

Aber wie gesagt für Vergleiche ist das vollkommen überflüssig wenn man schon alle Eigenschaften der Objekte in Variablen hat.

Gruß

p.s. Robocopy mit Parameter /L macht dir das frei Haus.
Mitglied: H41mSh1C0R
H41mSh1C0R 25.10.2016 um 13:53:45 Uhr
Goto Top
Hi,

Um die Textdateien kommen wir leider nicht rum da die zu vergleichenden Dateien von unterschiedlichen Rechnern stammen ^^, aber das war auch nicht die Frage. =)

D.h. textfile erzeugen mit Struktur und im 2ten Schritt werden diese verglichen.

Beim Expand bekommst du allerdings z.B. den $_.Name aber wie schauts aus wenn du den Teilpfad haben willst?

Gruß
Mitglied: 131301
131301 25.10.2016 aktualisiert um 13:58:14 Uhr
Goto Top
Zitat von @H41mSh1C0R:
Beim Expand bekommst du allerdings z.B. den $_.Name aber wie schauts aus wenn du den Teilpfad haben willst?
Hast du dir überhaupt schon mal alle Eigenschaften auf der Konsole angesehen?
Da gibt es alles was du brauchst frei Haus:
  • DirectoryName
  • Directory.Parent.Name
  • Directory.Parent.Fullname
  • Basename
  • etc.
Mitglied: H41mSh1C0R
H41mSh1C0R 25.10.2016 aktualisiert um 14:22:58 Uhr
Goto Top
Ich kann ja blind sein, allerdings ist kein Property dabei was mir den Subpfad liefert beginnend AB der Ebene z.B. dir1.

Und nein ich will ja nicht das was davor ist, sondern das was dahinter ist. Oder heißt hier das Zauberwort wieder regex?

So das es egal ist wo das auf den Clients liegt und die Substruktur trotzdem verglichen werden kann.
Mitglied: 131301
131301 25.10.2016 um 14:29:30 Uhr
Goto Top
Ich kann ja blind sein, allerdings ist kein Property dabei was mir den Subpfad liefert beginnend AB der Ebene z.B. dir1.
Wie soll das Script das wissen, also musst du es ihm sagen entweder durch ein Replace oder durch ein Split bei dem du die Anzahl der Backslashes deines vorgegebenen Pfades zählst und damit dann den Pfad der Datei splittest.
Mitglied: H41mSh1C0R
H41mSh1C0R 25.10.2016 um 14:32:06 Uhr
Goto Top
Gut also gibts keine Möglichkeit zu sagen gci ja und ab HIER (dir1) ist der Root?
Mitglied: 131301
131301 25.10.2016 aktualisiert um 14:34:49 Uhr
Goto Top
Nein. Das Root hast du ja schon in einer Variablen, also ist das nicht nötig.
Mitglied: H41mSh1C0R
H41mSh1C0R 25.10.2016 aktualisiert um 14:39:29 Uhr
Goto Top
Dann also so: In $cut habe ich dir1 oder dir2.

%{ $_.replace("$cut",$NULL)}  

So der nächste Schritt die Größe mit rein und dann geht's an das vergleichen. =)
Mitglied: 131301
Lösung 131301 25.10.2016 aktualisiert um 14:44:04 Uhr
Goto Top
Zitat von @H41mSh1C0R:
> %{ $_.replace("$cut",$NULL)}  
> 
Achtung, das ist keine gute Idee. Bei dieser Replace-Variante wird Groß und Kleinschreibung unterschieden. Das geht also unter Umständen schief.
Also entweder
%{$_.Fullname.toLower().Replace($cut.toLower(),'')}  
oder
%{$_.Fullname -replace "^$([regex]::Escape($cut))",''}  
So der nächste Schritt die Größe mit rein und dann geht's an das vergleichen. =)
Würde ich wenn dann nur in eine CSV schreiben.
Mitglied: H41mSh1C0R
H41mSh1C0R 25.10.2016 aktualisiert um 15:16:12 Uhr
Goto Top
Schonmal danke für die Hilfe.

Get-ChildItem $path -Recurse | Select-Object FullName, Length | %{$_.FullName.toLower().Replace($cut.toLower(), '')}| Export-Csv $ff -NoTypeInformation  

Im CSV lässt er die Spalte FullName komplett weg.

;(
Mitglied: 131301
131301 25.10.2016 aktualisiert um 15:20:19 Uhr
Goto Top
Logisch weil das dann kein Objekt ist, aber auch zu umständlich...
Get-ChildItem $path -Recurse | Select FullName, Length, @{n="RelativePath";e={$_.FullName.toLower().Replace($cut.toLower(), '')}} | export-csv $ff -delimiter ";" -NoType -Encoding UTF8  
Mitglied: H41mSh1C0R
H41mSh1C0R 25.10.2016 aktualisiert um 15:49:39 Uhr
Goto Top
hmm ok.

Also mit dem @.... hängst du somit eine Spalte "RelativePath" an mit gekürztem Pfad. *merk*

Nun das Vergleichen. =)

$ff = Import-Csv $firstFile
$sf = Import-Csv $secFile

Compare-Object -ReferenceObject $ff -DifferenceObject $sf -IncludeEqual -Property FullName, Length, RelativePath -passThru | %{
	IF ($_.SideIndicator -eq '<=') { Write-Host $_.FullName $_.SideIndicator -ForegroundColor 'red' }  
	IF ($_.SideIndicator -eq '=>') { Write-Host $_.FullName $_.SideIndicator -ForegroundColor 'yellow' }  
	IF ($_.SideIndicator -eq '==') { Write-Host $_.FullName $_.SideIndicator -ForegroundColor 'green' }  
}

Ich bekomme zwar den Indicator in der Ausgabe allerdings läßt er mir den Pfad weg, immo.
Also egal welches Property ich dort im Write-Host angebe.
Mitglied: 131301
Lösung 131301 25.10.2016 aktualisiert um 15:59:43 Uhr
Goto Top
Bei Import-CSV fehlt die Angabe des Delimiters!

Also mit dem @.... hängst du somit eine Spalte "RelativePath" an mit gekürztem Pfad. *merk*
Das ist keine Spalte sondern eine "Eigenschaft" und das Verfahren nennt sich Calculated Properties
Mitglied: H41mSh1C0R
H41mSh1C0R 25.10.2016 um 16:06:20 Uhr
Goto Top
Und wieder was gelernt, danke.

Zu der Ausgabe innerhalb des letzten % Blocks:

Der Indicator ist doch Teil des Objektes oder?

Der wird auch ausgegeben. Alle anderen Eigenschaften sind doch auch Teil des Objektes und beim Debuggen stehen dort auch die Werte drinnen.

Doch wieso gibt er sie nicht mit aus?
Mitglied: 131301
Lösung 131301 25.10.2016 aktualisiert um 16:11:34 Uhr
Goto Top
Zitat von @H41mSh1C0R:
Der Indicator ist doch Teil des Objektes oder?
Ja, wird beim Passthru als Eigenschaft dem Objekt als Member hinzugefügt.
Der wird auch ausgegeben. Alle anderen Eigenschaften sind doch auch Teil des Objektes und beim Debuggen stehen dort auch die Werte drinnen.
Doch wieso gibt er sie nicht mit aus?
Weil du es falsch ausgibst der interpretiert das als zusätzlichen Parameter von write-host und nicht als das auszugebende...
Write-Host "$($_.FullName) $($_.SideIndicator)" -ForegroundColor 'red'
Mitglied: H41mSh1C0R
H41mSh1C0R 25.10.2016 um 16:21:15 Uhr
Goto Top
bildschirmfoto 2016-10-25 um 16.17.35

In der Ausgabe(ersten beiden Zeilen) rechts gibt es trotzdem noch nicht korrekt aus.
Mitglied: 131301
131301 25.10.2016 aktualisiert um 16:31:46 Uhr
Goto Top
Weil du sie nicht wie oben geschrieben angepasst hast face-smile und es immer noch falsch angegeben hast.
Mitglied: H41mSh1C0R
H41mSh1C0R 25.10.2016 aktualisiert um 16:35:37 Uhr
Goto Top
In den ersten beiden zeilen ja, aber der Vergleich auf "==" in der dritten Zeile den habe ich in der Form geschrieben wie von dir angegeben und rechts in der Ausgabe kommt trotzdem nix.

=)

Jetzt mal alle 3 Zeilen angepasst:

bildschirmfoto 2016-10-25 um 16.34.52
Mitglied: 131301
131301 25.10.2016 aktualisiert um 17:08:02 Uhr
Goto Top
Geht hier einwandfrei, du machst also noch irgendwo einen Fehler. Keine Ahnung wo ich habe deine Daten hier nicht...
Mitglied: H41mSh1C0R
H41mSh1C0R 25.10.2016 aktualisiert um 17:23:23 Uhr
Goto Top
bildschirmfoto 2016-10-25 um 17.16.13

bildschirmfoto 2016-10-25 um 17.17.12

Inhalt in der Datei als auch im $_ ist da nur kommt nix in der Konsole an bei der Ausgabe außer der SideIndicator.

;(

Test Script immo:

$path = "C:\temp\compare\dir1"  
$cut = "C:\temp\compare\dir1\"  
$firstfile = "C:\temp\test.csv"  
		
$a = Get-ChildItem $path -Recurse | Select FullName, Length, @{ n = "RelativePath"; e = { $_.FullName.toLower().Replace($cut.toLower(), '') } } | export-csv $firstfile -delimiter ";" -NoType -Encoding UTF8  
	
$path2 = "C:\temp\compare\dir2"  
$cut2 = "C:\temp\compare\dir2\"  
$secondfile = "C:\temp\test2.csv"  
	
$b = Get-ChildItem $path2 -Recurse | Select FullName, Length, @{ n = "RelativePath"; e = { $_.FullName.toLower().Replace($cut2.toLower(), '') } } | export-csv $secondfile -delimiter ";" -NoType -Encoding UTF8  
	
	
$ff = Import-Csv $firstFile
$sf = Import-Csv $secondfile
	
Compare-Object -ReferenceObject $ff -DifferenceObject $sf -IncludeEqual -Property FullName, Length, RelativePath -passThru | %{
	IF ($_.SideIndicator -eq '<=') { Write-Host "$($_.FullName) $($_.SideIndicator)" -ForegroundColor 'red' }  
	IF ($_.SideIndicator -eq '=>') { Write-Host "$($_.FullName) $($_.SideIndicator)" -ForegroundColor 'yellow' }  
	IF ($_.SideIndicator -eq '==') { Write-Host "$($_.FullName) $($_.SideIndicator)" -ForegroundColor 'green' }		  
}
		

Die CSV schaut noch ok aus. Im Watcher hat alles " " bis auf FullName, ka ob das da klemmt?
Mitglied: 131301
Lösung 131301 25.10.2016 um 17:34:59 Uhr
Goto Top
Ich hab doch oben schon geschrieben das dir die Angabe des Delimiters bei Import-CSV fehlt!
$ff = Import-Csv $firstFile -Delimiter ";"
$sf = Import-Csv $secondfile -Delimiter ";"
Mitglied: H41mSh1C0R
H41mSh1C0R 25.10.2016 um 17:37:52 Uhr
Goto Top
*GNARF*

Danke sehr, geht. =)