Powershell - Wieso fehtl ein Stück vom String?
Hallo.
Erkläre mein Problem am besten gleich am Beispiel:
Code:
$source = 'E:\Powershell_Skripts\99 - Ordner für Tests\Source\MFU'
$filter = "*.dfq"
$i = 0
$DelTime = -1
[Array]$file_list = @()
foreach ($file in (Get-ChildItem $source -Recurse).FullName) {
if ($file -like $filter -and $file.LastAccesstiime -le (get-date).AddMinutes($DelTime)) {
$i++
Write-Host "Datei-Nr.: $i heißt: $file"} # Nur für Test
$file_list += $file
}
In der Schleife wird das Ausgegeben:
Datei-Nr.: 1 heißt: E:\Powershell_Skripts\99 - Ordner für Tests\Source\MFU\15258\Drehen.dfq
Wenn ich einen Index des Arrays ausgebe mit:
write-host ($file_list[0])
Ist es nur noch das (also ohne der Datei am Schluß):
E:\Powershell_Skripts\99 - Ordner für Tests\Source\MFU\15258
Bräuchte für die Nachbearbeitung aber den gesamten Pfad mit Datei. Was mache ich falsch?
3 Antworten
Nö da fehlt kein Stück vom String...
Da du auch Ordner ermittelst hängt da natürlich kein Dateiname dran...
Dies schließt Du aus, indem du mit dem Parameter -File nur Dateien suchst.
Das nächste Problem ist, das Du an $file lediglich eine Liste von fullnames übergibst und somit garnicht auf die Dateizeiten zugreifen kannst.
Die Macht von Powershell liegt in der Pipe...
$source = 'x:\Ordner der dursucht wird'
$filter = "*.extension"
$DelTime = -1
# lass Get_ChildItem alles wozu es fähig ist selbst tun, dazu gehört auch das Filtern auf wildcerds für Dateinamen (das retutiert schonmal den Input für die Pipeline)
#jage die komletten Fileobjekte in die Pipeline ($_ ist immer das aktuell übergebene Objekt)
$FileNames_list=@(Get-ChildItem -Path $source -Filter $filter -Recurse -File -ErrorAction silent |
Where-Object {$_.LastAccessTime -le (get-date).AddMinutes($DelTime)} | #jetz brauchst du nur noch filtern was gci nicht kann
ForEach-Object -Begin {$i = 0} -Process { #hier kommen nur noch die Objekte an, welche welche durch alle Filter gerutscht sind
Write-Host "Datei-Nr.: $i heißt: $($_.FullName)" -fo green #Writehost ist gut zum Beobachten, da es immer auf den Bildschirm schreibt aber nicht in die Pipe
$i++
$_.FullName #wird in die Pipe geschrieben
} # ...und da kein weiterer Pipefilter folgt ins Array, welches an die Zielvariable übergeben wird
)
$FileNames_list[0]
'alle anzeigen
'
$FileNames_list
pause
der Vorteil dieses vorgehens ist : Du Quälst die Speicherverwaltung nicht mit mit Erweitern von Arrays , die Pipe ist immer schneller als ein foreach-loop welcher mit globalen Variablen herumzirkelt.
obiges war "Schönschrift" mit übertriebener Kommentierung
Das geht natürlich auch schluderig:
$FileNames_list=@( dir $source -Filter $filter -Recurse -File -EA silent | ?{$_.LastAccessTime -le (get-date).AddMinutes($DelTime)} |%{ $_.FullName } )
$FileNames_list
pause
Wenn Du mit Foreach-Object operierst, musst Du das dort ermittelte Ergebnis auch der Pipe übergeben.
1..10| % {
$_tempVar = $_*$_ #fuchtbaarkomlexe Formel
#$_*$_ hätte in diesem Fall auch gereicht
$_tempVar #Ergebnis der Pipe übergeben
}
Allerdings wäre es Unsinn für ein bloße Überprüfung jedes Elements (ohne Alternativzweig) % zu bemühen.
1..10| ?{ !($_ % 2) }
...prüft einfach ob das aktuelle Element ohne Rest durch 2 teilbar ist und in der Pipe verbleiben darf... . in einem solchen Fall musst Du nichts selbst in die Pipe schreiben. das ?{...} ist einfach nur ein Sieb, welches bestehendes Zeug durchlässt oder nicht.
Spätestens wenn du deinen Code richtig einrücken würdest, solltest du den Fehler sehen. Du fügst der Liste jeden Eintrag hinzu, über den iteriert wird. An Stelle 0 steht also erst einmal nur das Verzeichnis selbst.
Verschiebe
$file_list += $file
also in den if-Rumpf.
Hi. Danke für deine Antwort. Hab jetzt wirklich noch einen Moment gebraucht bis ich meinen ... Fehler gesehen hab.
Und du hast auch recht mit dem einrücken. Hab irgendwie noch keine Optimale Anordnung/Einrückung für mich gefunden wie ich meinen Code/Funktionen etc. Ordentlich lesbar mache.
Solange immer nur eine Klammer ist , ist das klar. was ich meinte war wenn Klammern in Klammern ... verwendet werden.
Da hab ich jetzt schon ein paar verschiedene Arten zur Einteilung gesehen.
Ich habe vor ein paar Jahren Python versucht zu lernen (hab leider schon wieder viel vergessen).
Soweit ich mich erinnere hatte ich da eine bessere Struktur hinbekommen, bzw. ich glaub da war es teilweise sogar vorgeschrieben.
Dann würde ich den Code um einen Tab (bzw. 2/4/8 Leerzeichen) einrücken.
k {
& {
r {
}
}
}
So sind Blockanfang und -ende auf einer vertikalen Linie.
Bei Python kommt man ohne die geschweiften Klammern aus, allerdings sind die Einrückungen Zwang.
def do_something():
value = 1
if value == 1:
print("Value is 1")
Bei Powershell sind Einrückungen eigentlich nur Kosmetik.
Eine Pipeleine schreibt man gewöhnlich in einen Zeile . Ausgenommen Foreach-Objekt, dann rückt man den Rumpf ein.
$variable = Pipeinput | Filter | Filter | % {
do Somethig
output to Pipe
} | more filters ....
bei komplexeren Filtern:
$variable = Pipeinput |
Filter |
Filter |
% {
do Somethig
output to Pipe
} |
more filters ....
Mal von der Einrückung abgesehen (auf die bin ich beim lesen der Frage selbst reingefallen): Ich würde dir empfehlen, nicht den Dateinamen auszulesen, sondern die Datei-Objekte selbst im Array zu speichern. Das ist meistens besser, wenn du damit weiter arbeiten willst.
Das "Get-Childitem" (ich kürze das immer ab mit "dir") hat auch noch einen Parameter -File, mit dem du sagen kannst, dass du nur Dateien und keine Ordner zurückkriegen willst. Und du kannst den Filter auch da direkt angeben.
Also z.B.
$source = 'E:\Powershell_Skripts\99 - Ordner für Tests\Source\MFU\'
// Alle *.dfq Dateien in dem Ordner suchen
$file_list = @(dir $source "*.dfq")
// Alle Dateien ausgeben, die vor mehr als einer Minute bearbeitet wurden
($file_list | where LastAccessTime -le (Get-Date).AddMinutes(-1)).FullName
Hallo.
Vielen Dank dafür, aber bei mir funktioniert das nicht.
Bei
$file_list = @(dir $source)
bekomme ich (in meinem Fall) 3 Objekte in die Liste. Das sind aber nur Ordner und keine Dateien
Bei
$file_list = @(dir $source "*.dfq")
sind es 0 Objekte.
Da nichts in der Variable $file_list gespeichert wird kann ich nicht damit weitermachen. Oder ich mach was falsch.
Hallo Wiedermal.
Erstmal vielen Dank für deine Hilfe.
Hab zuerst ca. eine Stunde in Dr. Google gesetzt weil ich einen Kommentar von dir überlesen habe. (Obwohl du es eh so schön geschrieben hattest)
Hab zuerst nicht raus gefunden wieso meine Liste danach immer leer war.
Das hatte ich überlesen: