Frage

Der folgende code gibt mir ein array von PSCustomObjects, wie ich es bekommen kann, um ein array von Zeichenfolgen zurückzugeben?

$files = Get-ChildItem $directory -Recurse | Select-Object FullName | Where-Object {!($_.psiscontainer)}

(Als sekundäre Frage, was ist der psiscontainer Teil für?Ich habe die kopiert, die aus einer Beispiel-online)

Post-Editieren Akzeptieren: Zwei gute Antworten, ich wünschte, ich könnte markieren Sie die beiden von Ihnen.Ausgezeichnet die ursprüngliche Antwort.

War es hilfreich?

Lösung

Sie müssen nur die Eigenschaft, die Sie von den Objekten wollen herausgreifen. FullName in diesem Fall.

$files = Get-ChildItem $directory -Recurse | Select-Object FullName | Where-Object {!($_.psiscontainer)} | foreach {$_.FullName}

Edit: Erklärung für Markus, der fragt,

"Was bedeutet die foreach tun Was das vorbei ist aufzählt?"

Sung Meister Erklärung ist sehr gut, aber ich werde eine Komplettlösung hier hinzufügen, da es hilfreich sein könnte.

Das Schlüsselkonzept ist die Pipeline. Bild, um eine Reihe von Pingpong Kugeln rollen ein enges Rohr einer nach der anderen. Dies sind die Objekte in der Pipeline. Jede Stufe der Pipeline - die durch das Rohr getrennt Codesegmente (|) Zeichen - hat wird ein Rohr hinein und Rohr aus ihm gehen. Der Ausgang einer Stufe ist mit dem Eingang der nächsten Stufe verbunden. Jede Stufe nimmt die Objekte, wie sie ankommen, tut Dinge, um sie und sendet sie zurück in die Ausgangsleitung oder sendet neue Ersatz-Objekte.

Get-ChildItem $directory -Recurse

Get-ChildItem Wanderungen durch das Dateisystem Filesysteminfo-Objekte erstellen, die jede Datei und Verzeichnis repräsentieren sie trifft, und setzt sie in die Pipeline.

Select-Object FullName

Select-Object nimmt jedes Filesysteminfo-Objekt, wie es kommt, schnappt sich die Fullname-Eigenschaft von ihm (das ist ein Weg, in diesem Fall ist), setzt diese Eigenschaft in ein neues benutzerdefiniertes Objekt es geschaffen hat, und legt das benutzerdefinierte Objekt aus in die Pipeline.

Where-Object {!($_.psiscontainer)}

Dies ist ein Filter. Es dauert jedes Objekt, prüft sie und sendet sie wieder heraus oder verwirft es auf einer Bedingung abhängig. Ihr Code hat hier einen Fehler, durch die Art und Weise. Die benutzerdefinierten Objekte, die hier ankommen keine psiscontainer Eigenschaft. In dieser Phase nicht wirklich etwas tun. Sung Meister der Code ist besser.

foreach {$_.FullName}

Foreach, deren langer Name ist ForEach-Object, greift jedes Objekt, wie es kommt, und hier greift die Eigenschaft Fullname, eine Zeichenfolge, von ihm. Nun, hier ist die subtile Teil: Jeder Wert, der nicht verbraucht wird, das heißt, nicht durch eine Variable erfasst wird oder in irgendeiner Weise unterdrückt, wird in die Ausgangsleitung gesetzt. Als Experiment versuchen, die Bühne mit diesem ersetzen:

foreach {'hello'; $_.FullName; 1; 2; 3}

versuchen es tatsächlich aus und überprüfen Sie die Ausgabe. Es gibt vier Werte in diesem Codeblock. Keiner von ihnen ist verbraucht. Beachten Sie, dass sie alle in der Ausgabe erscheinen. Nun versuchen Sie dies:

foreach {'hello'; $_.FullName; $ x = 1; 2; 3}

Beachten Sie, dass einer der Werte wird durch eine variable erfasst wird. Es ist nicht in der Ausgabe-Pipeline erscheinen.

Andere Tipps

Um die Zeichenfolge für die Dateinamen erhalten Sie verwenden können,

$files = Get-ChildItem $directory -Recurse | Where-Object {!($_.psiscontainer)} | Select-Object -ExpandProperty FullName

Der -ExpandProperty Parameter können Sie anhand eines Objekts, um wieder auf die Art der Eigenschaft angegeben.

Weitere Tests zeigen, dass dies nicht mit V1 nicht funktionierte, aber diese Funktionalität ist als die V2 CTP3 festgelegt.

Frage #1

Ich habe entfernt "select-object" Teil - das ist redundant und verschoben ", wo" filter vor der "foreach" - im Gegensatz zu dangph Antwort - Filter so bald wie möglich, so, dass Sie es mit nur eine Teilmenge dessen, was Sie zu tun haben in der nächsten pipe-line.

$files = Get-ChildItem $directory -Recurse | Where-Object {!$_.PsIsContainer} | foreach {$_.FullName}

Das code-snippet, das im wesentlichen liest

  • Holen Sie sich alle Dateien mit vollständigen Pfad aller Dateien rekursiv (Get-ChildItem $directory -Recurse)
  • Filtern Verzeichnisse (Where-Object {!$_.PsIsContainer})
  • Rückkehr vollständige Dateiname nur (foreach {$_.FullName})
  • Speichern Sie alle Dateinamen in $files

Beachten Sie, dass für foreach {$_.FullName}, in powershell, Letzte Anweisung in einem Skript-block ({...}) zurückgegeben wird, in diesem Fall $_.FullName vom Typ string

Wenn Sie wirklich brauchen, um ein raw-Objekt, Sie brauchen nicht, etwas zu tun, nachdem loszuwerden "select-object".Wenn Sie wurden zu verwenden, Wählen Sie " -Objekt zugreifen möchten, raw-Objekt, verwenden Sie "PsBase", das ist eine ganz andere Frage(Thema) - Siehe "Was ist mit PSBASE, PSEXTENDED, PSADAPTED, und PSOBJECT?"weitere Informationen zu diesem Thema

Frage #2

Und auch das filtern von !$_.PsIsContainer bedeutet, dass Sie ohne eine container-level-Objekte, In Ihrem Fall sind, machst du Get-ChildItem auf einem Dateisystem provider(Sie können sehen, PowerShell-Anbieter über Get-PsProvider), damit der container ein DirectoryInfo(Ordner)

PsIsContainer bedeutet, verschiedene Dinge unter verschiedenen PowerShell-Anbieter;z.B.) Für Registrierung Anbieter, PsIsContainer Typ Microsoft.Win32.RegistryKey Versuchen Sie dies:

>pushd HKLM:\SOFTWARE
>ls | gm

[UPDATE] folgende Frage: Was bedeutet der foreach tun?Was ist das aufzählen vorbei? Um zu klären, "foreach" ist ein alias für "Foreach-Object" Sie können herausfinden, über,

get-help foreach

-- oder --

get-alias foreach

Jetzt in meiner Antwort, "foreach" ist das aufzählen jedes Objekt Instanz vom Typ FileInfo zurück aus früheren pipe (was gefiltert wurde, Verzeichnisse). FileInfo hat eine Eigenschaft namens FullName und das ist es, was "foreach" ist Aufzählung über.
Und Sie Referenz-Objekt übergeben durch pipeline-durch eine spezielle pipeline variable namens"$_", die der Typ FileInfo im script-block Kontext von "foreach".

Für V1, fügen Sie den folgenden Filter auf Ihr Profil:

filter Get-PropertyValue([string]$name) { $_.$name }

Dann können Sie dies tun:

gci . -r | ?{!$_.psiscontainer} | Get-PropertyName fullname

BTW, wenn Sie die Powershell Community-Erweiterungen Sie dies bereits haben.

Im Hinblick auf die Fähigkeit Select-Object verwenden -Expand in V2, ist es ein netter Trick, aber nicht auf der Hand und ist wirklich nicht das, was Select-Object noch -Expand für gemeint war. -Expand dreht sich alles um Abflachung wie LINQ Select und Select-Object ist über Projektion von mehreren Eigenschaften auf ein benutzerdefiniertes Objekt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top