So filtern Sie mehrere Zeichenfolgen in einem PowerShell-Kopierskript ordnungsgemäß


80

Ich verwende das PowerShell-Skript aus dieser Antwort , um eine Dateikopie zu erstellen. Das Problem tritt auf, wenn ich mithilfe des Filters mehrere Dateitypen einschließen möchte.

Get-ChildItem $originalPath -filter "*.htm"  | `
   foreach{ $targetFile = $htmPath + $_.FullName.SubString($originalPath.Length); ` 
 New-Item -ItemType File -Path $targetFile -Force;  `
 Copy-Item $_.FullName -destination $targetFile }

funktioniert wie ein Traum. Das Problem tritt jedoch auf, wenn ich mithilfe des Filters mehrere Dateitypen einschließen möchte.

Get-ChildItem $originalPath ` 
  -filter "*.gif","*.jpg","*.xls*","*.doc*","*.pdf*","*.wav*",".ppt*")  | `
   foreach{ $targetFile = $htmPath + $_.FullName.SubString($originalPath.Length); ` 
 New-Item -ItemType File -Path $targetFile -Force;  `
 Copy-Item $_.FullName -destination $targetFile }

Gibt mir folgenden Fehler:

Get-ChildItem : Cannot convert 'System.Object[]' to the type 'System.String' required by parameter 'Filter'. Specified method is not supported.
At F:\data\foo\CGM.ps1:121 char:36
+ Get-ChildItem $originalPath -filter <<<<  "*.gif","*.jpg","*.xls*","*.doc*","*.pdf*","*.wav*",".ppt*" | `
    + CategoryInfo          : InvalidArgument: (:) [Get-ChildItem], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.GetChildItemCommand

Ich habe verschiedene Iterationen von Klammern, keine Klammern -filter, -includeund definiert die Einschlüsse als Variable (zB $fileFilter) und jedes Mal den obigen Fehler erhalten, und immer zeigt auf was auch immer folgt -filter.

Die interessante Ausnahme ist, wenn ich codiere -filter "*.gif,*.jpg,*.xls*,*.doc*,*.pdf*,*.wav*,*.ppt*". Es gibt keine Fehler, aber ich bekomme keine Ergebnisse und nichts zurück zur Konsole. Ich vermute, ich habe versehentlich einen Impicit andmit dieser Aussage codiert ?

Was mache ich also falsch und wie kann ich das korrigieren?

Antworten:


194

-Filter akzeptiert nur eine einzelne Zeichenfolge. -Include akzeptiert mehrere Werte, qualifiziert jedoch das Argument -Path . Der Trick besteht darin, \*an das Ende des Pfads anzuhängen und dann mit -Include mehrere Erweiterungen auszuwählen. Übrigens ist das Zitieren von Zeichenfolgen in Cmdlet-Argumenten nicht erforderlich, es sei denn, sie enthalten Leerzeichen oder Shell-Sonderzeichen.

Get-ChildItem $originalPath\* -Include *.gif, *.jpg, *.xls*, *.doc*, *.pdf*, *.wav*, .ppt*

Beachten Sie, dass dies unabhängig davon funktioniert, ob $ originalPath mit einem Backslash endet, da mehrere aufeinanderfolgende Backslashes als einzelnes Pfadtrennzeichen interpretiert werden. Versuchen Sie zum Beispiel:

Get-ChildItem C:\\\\\Windows

5
WooHoo! Dieser \*Trick hat gerade sechs Probleme gelöst. Super & Danke!
Dwwilson66

17
Beachten Sie, dass der Platzhalter ( \*) nicht benötigt wird, wenn er -Recurseangegeben wird.
Ohad Schneider

Aus irgendeinem Grund funktioniert dies nicht bei der Suche nach Verzeichnissen?
Ross Presser

Durch Hinzufügen von -Recurse können Unterordner erreicht werden
Derek Evermore

2

So etwas sollte funktionieren (es hat für mich funktioniert). Der Grund für die Verwendung -Filteranstelle von -Includeist, dass include im Vergleich zu einen enormen Leistungseinbruch bedeutet -Filter.

Im Folgenden werden nur die einzelnen Dateitypen und mehrere Server / Arbeitsstationen in separaten Dateien wiederholt.

##  
##  This script will pull from a list of workstations in a text file and search for the specified string


## Change the file path below to where your list of target workstations reside
## Change the file path below to where your list of filetypes reside

$filetypes = gc 'pathToListOffiletypes.txt'
$servers = gc 'pathToListOfWorkstations.txt'

##Set the scope of the variable so it has visibility
set-variable -Name searchString -Scope 0
$searchString = 'whatYouAreSearchingFor'

foreach ($server in $servers)
    {

    foreach ($filetype in $filetypes)
    {

    ## below creates the search path.  This could be further improved to exclude the windows directory
    $serverString = "\\"+$server+"\c$\Program Files"


    ## Display the server being queried
    write-host “Server:” $server "searching for " $filetype in $serverString

    Get-ChildItem -Path $serverString -Recurse -Filter $filetype |
    #-Include "*.xml","*.ps1","*.cnf","*.odf","*.conf","*.bat","*.cfg","*.ini","*.config","*.info","*.nfo","*.txt" |
    Select-String -pattern $searchstring | group path | select name | out-file f:\DataCentre\String_Results.txt

    $os = gwmi win32_operatingsystem -computer $server
    $sp = $os | % {$_.servicepackmajorversion}
    $a = $os | % {$_.caption}

    ##  Below will list again the server name as well as its OS and SP
    ##  Because the script may not be monitored, this helps confirm the machine has been successfully scanned
        write-host $server “has completed its " $filetype "scan:” “|” “OS:” $a “SP:” “|” $sp


    }

}
#end script

Dies ist sehr richtig und in 5 ähnlichen Fragen hat hier niemand darauf hingewiesen, dass es, obwohl wir es nicht -filter *.jpg, *.pngkönnen, immer noch schneller sein könnte, -filter * .jpg auf einmal zu tun, als -filter * .png zu tun und sich den Ergebnissen anzuschließen, als mach eins -Include *.jpg, *.png". Ich habe einen Ordner mit 126.000 Dateien und 18.000 Ordnern. Ich suche rekursiv nach einer Datei und einem Ordner in jedem Ordner. Die Verwendung von -Filter dauert 5 Sekunden und die Verwendung von -Include 30 Sekunden. Zweimaliges Filtern in 10 Sekunden ist dreimal schneller als einmaliges Einschließen.
Papo

0
Get-ChildItem $originalPath\* -Include @("*.gif", "*.jpg", "*.xls*", "*.doc*", "*.pdf*", "*.wav*", "*.ppt")

Willkommen bei Stack Overflow! Diese Antwort wurde in der Warteschlange für Überprüfungen von geringer Qualität angezeigt, vermutlich weil Sie den Inhalt nicht erklärt haben. Wenn Sie dies erklären (in Ihrer Antwort), erhalten Sie mit größerer Wahrscheinlichkeit mehr positive Stimmen - und der Fragesteller lernt tatsächlich etwas!
Der Kerl mit dem Hut

2
Außerdem wiederholt es den Code aus der Antwort, die ich zuvor gepostet habe, mit der Ausnahme, dass es die Liste der Erweiterungen in einem Array-Ausdrucksbewertungsoperator ( @()) enthält, was überflüssig ist, da eine durch Kommas getrennte Liste von Natur aus als Array ausgewertet wird.
Adi Inbar

-2

1
Das hat nicht funktioniert. :( -filter -include *.file, *.types -filter -include (*.file, *.types), -filter -include "*.file", "*.types"und -filter -include ("*.file", "*.types")alle wie oben pro meine Frage errored aus der Beseitigung. -filterParameter und nur einschließlich der -include(gleichen Iterationen von Zitaten und Pars) hat nicht zur Folge haben Laufzeitfehler, aber es war im Zielverzeichnis keine Ergebnismenge.
dwwilson66
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.