
Ich habe Folgendes gefunden, um den Inhalt eines Ordners und seiner Unterordner (nur Dateien) in einer CSV-Datei abzurufen:
dir -recurse | Where-Object { !$_.PSIsContainer } | Select FullName |
convertto-csv | out-file "test.csv"
Allerdings möchte ich statt des vollständigen Pfads den relativen Pfad erhalten (relativ zum Stammverzeichnis, von dem aus ich den Befehl ausführe).
Kann jemand helfen?
Danke!
Antwort1
Eine Möglichkeit, eine richtige CSV-Datei zu erhalten, besteht darin, die Ausgabe meines Kommentars zu umschließen:
Get-ChildItem -Recurse -Name -File |
ForEach-Object -begin {'"RelativePath"'}{'"{0}"' -f $_}|
Out-File "test.csv"
Oder verwenden Sie eine berechnete Eigenschaft, um das Startverzeichnis aus der FullName
Eigenschaft zu entfernen.
$StartDir = "$ENV:USERPROFILE\Documents\"
Get-ChildItem -Path $StartDir -File -Recurse |
Select-Object @{n='RelativePath';e={$_.FullName -replace [regex]::escape($StartDir)}}|
Export-Csv 'test.csv' -NoTypeInformation
Antwort2
Diese Frage vermittelt den Eindruck, dass Sie mit PowerShell noch nicht vertraut sind. Daher ist es wichtig, dass Sie sich damit vertraut machen, um Missverständnisse, schlechte Angewohnheiten, Fehler und ernsthafte Frustrationen, die Ihnen garantiert begegnen werden, zu begrenzen bzw. zu vermeiden. Gehen Sie auf YouTube/MSDN Channel9 und suchen Sie nach PowerShell für Anfänger, Fortgeschrittene und Experten sowie PowerShell-Dateisystemverwaltung und PowerShell-Datei- und Ordnerverwaltung.
PowerShell versucht in vielen Fällen, Dinge zu erzwingen, aber es versucht nicht, herauszufinden, was Sie tun möchten. Sie müssen ihm sagen, was es tun soll. Nun, das gilt für jede Computersprache.
Ihr Problem hier ist, dass Sie sagen ...
(relativ zum Stammverzeichnis, von wo aus ich den Befehl ausführe)
... nun, Sie könnten sich in einem Pfad befinden, der sich auf der X-Ebene des Stammlaufwerks befindet, sodass Sie sich jetzt in einem untergeordneten Laufwerk befinden, und die Extrapolation ist, dass Sie dies nur vom untergeordneten Laufwerk aus möchten. Hier liegt das Problem bei diesem Denkprozess.
Speichern Sie dies in einer Textdatei. Dann hätten Sie den Laufwerkspfad nicht mehr und müssen ihn bei der erneuten Verwendung kennen und manuell erneut eingeben, um die Dateien erneut verwenden zu können.
Ich bin mir also nicht sicher, was Ihr Anwendungsfall für diesen Aufwand ist, aber logischerweise wird es sich rächen.
Nehmen wir also an, ich bin hier:
Push-Location -Path 'E:\Temp'
Dann führen wir dies aus
Get-ChildItem -recurse |
Where-Object { !$_.PSIsContainer } | Select-Object -Property FullName
# Results
FullName
--------
E:\Temp\about_ReGet-ChildItemection Microsoft Docs.url
...
E:\Temp\ZipMultiFolder.zip
E:\Temp\Folder\Log_20190419.txt
...
E:\Temp\Reports\NewFiles.zip
...
Also, hier erhalten wir einfach den aktuellen Standort ...
Get-ChildItem -recurse |
Where-Object { !$_.PSIsContainer } |
Select-Object -Property @{Name = 'RelativePath';Expression = {"\$($pwd.Drive.CurrentLocation)\$($PSItem.Name)"}}
Hier erhalten wir also nur den aktuellen Pfad, in dem wir uns befinden, und fragen nur nach dem Dateinamen, nicht nach dem vollständigen Namen
# Results
RelativePath
------------
\Temp\about_ReGet-ChildItemection Microsoft Docs.url
...
\Temp\ZipMultiFolder.zip
\Temp\Folder\Log_20190419.txt
...
\Temp\Reports\NewFiles.zip
...
Wenn wir dies als CSV ausgeben, haben Sie keine Ahnung, von welchem Laufwerk dies stammt. Sie müssen jetzt also jedes Laufwerk auf Ihrem Computer durchsuchen, um sie zu finden, oder sich merken, wo Sie waren, als Sie dies getan haben.
Wenn Sie ein Kind ausschalten, passiert das Gleiche. Natürlich erhalten Sie es, aber wo befindet es sich wirklich? Auf Ihrem System oder auf einem Netzwerklaufwerk, das Sie zugeordnet haben.
Push-Location -Path 'E:\Temp\Folder'
Dann führen wir dies aus
Get-ChildItem -recurse |
Where-Object { !$_.PSIsContainer } | Select-Object -Property FullName
# Results
FullName
--------
E:\Temp\Folder\Log_20190419.txt
E:\Temp\Folder\New Bitmap Image.bmp
E:\Temp\Folder\New Text Document - Copy.txt
E:\Temp\Folder\New Text Document.txt
Get-ChildItem -recurse |
Where-Object { !$_.PSIsContainer } |
Select-Object -Property @{Name = 'RelativePath';Expression = {"\$($pwd.Drive.CurrentLocation)\$($PSItem.Name)"}}
RelativePath
------------
\Temp\Folder\Log_20190419.txt
\Temp\Folder\New Bitmap Image.bmp
\Temp\Folder\New Text Document - Copy.txt
\Temp\Folder\New Text Document.txt
Und wenn Sie hier sagen, Sie wollen die übergeordnete Wurzel nicht, dann schalten Sie diese aus.
Das bedeutet jedoch nicht nur, dass Sie nicht wissen, von welchem Laufwerk es stammt, sondern auch, dass Sie nicht wissen, von welchem übergeordneten Stammlaufwerk es stammt.
Also, ich sag's einfach.
Übrigens ist es eine bewährte Methode, in Skripten den vollständigen Cmdlet-Namen zu verwenden. Abkürzungen/Aliase sind für interaktive Dinge in Ordnung. Sicher, wir sind alle daran gewöhnt, „dir“ zu verwenden, aber die Abkürzung für „Get-ChildItem“ ist „gci“, was genauso kurz ist wie „did“, aber, Sie wissen schon.
Get-Alias -Definition Get-ChildItem |
Format-Table -AutoSize
CommandType Name Version Source
----------- ---- ------- ------
Alias dir -> Get-ChildItem
Alias gci -> Get-ChildItem
Alias ls -> Get-ChildItem
Aber hey, Gewohnheiten sind wirklich schwer abzulegen. ;-} --- --- und die klugen Entscheidungen sind diejenigen, die für uns funktionieren, egal, was andere denken. ;-}
Nun, diejenigen, die Ihnen folgen, müssen Stellung beziehen. Ein guter PowerShell-Benutzer zu sein, ist also wirklich eine gute Sache.
Übrigens, wenn Sie dies in einem Skript tun möchten, gibt es auch für diese Art von Dingen eine automatische Variable. Sie ruft den Ort ab, an dem das Skript ausgeführt wurde, und alles, was mit diesem Ort verknüpft ist.
Siehe diesen Artikel.
Fügen Sie Skriptflexibilität mit relativen Dateipfaden hinzu