Як правильно фільтрувати кілька рядків у сценарії копіювання PowerShell


80

Я використовую сценарій PowerShell з цієї відповіді для копіювання файлу. Проблема виникає, коли я хочу включити кілька типів файлів за допомогою фільтра.

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

працює як мрія. Однак проблема виникає, коли я хочу включити кілька типів файлів за допомогою фільтра.

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 }

Видає мені таку помилку:

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

У мене є різні ітерації дужок, без дужок -filter, -include, визначення включень як змінної (наприклад, $fileFilter) і кожен раз отримую вищевказану помилку, і завжди вказує на те , що слід -filter.

Цікавий виняток з цього - коли я кодую -filter "*.gif,*.jpg,*.xls*,*.doc*,*.pdf*,*.wav*,*.ppt*". Помилок немає, але я не отримую результатів і нічого не повертаю на консоль. Я підозрюю, що ненароком закодував імпіцит andцим твердженням?

То що я роблю не так, і як я можу це виправити?

Відповіді:


194

-Фільтр приймає лише один рядок. -Include приймає кілька значень, але відповідає аргументу -Path . Фокус полягає у додаванні \*до кінця шляху, а потім за допомогою -Include вибрати кілька розширень. До речі, цитування рядків непотрібно в аргументах командлета, якщо вони не містять пробілів або спеціальних символів оболонки.

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

Зверніть увагу, що це буде працювати незалежно від того, закінчується $ originalPath зворотною косою рисою, оскільки кілька послідовних зворотних скісних рисок інтерпретуються як один роздільник шляху. Наприклад, спробуйте:

Get-ChildItem C:\\\\\Windows

5
WooHoo! Цей \*фокус щойно вирішив близько шести проблем. Чудово та спасибі!
dwwilson66

17
Зверніть увагу, що підстановочний знак ( \*) не потрібен, коли -Recurseвказано.
Охад Шнайдер,

чомусь це не працює під час пошуку каталогів?
Ross Presser

Додавання -Recurse дозволяє дістатися до підпапок
Дерек Евермор

2

Щось на зразок цього мало б спрацювати (це вдалося для мене). Причина бажання використовувати -Filterзамість того -Include, що включення займає величезний показник продуктивності порівняно з -Filter.

Нижче просто цикли кожного типу файлу та декількох серверів / робочих станцій, вказаних в окремих файлах.

##  
##  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

це дуже вірно, і в 5 подібних запитаннях тут ніхто не вказував, що хоча ми не можемо зробити -filter *.jpg, *.pngце, можливо, все-таки швидше зробити -filter * .jpg за один раз, ніж do -filter * .png та приєднати результати, ніж зробити одне -Include *.jpg, *.png". У мене є папка, що містить 126 тис. Файлів та 18 тис. Папок. Я шукаю один файл і одну папку в кожній папці рекурсивно. використання -Filter займає 5 секунд, а використання -Include 30 секунд. Виконання -Фільтр два рази за 10 секунд втричі швидший за один -Включіть перехід.
папо

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

Ласкаво просимо до Stack Overflow! Ця відповідь з’явилась у черзі огляду низької якості, мабуть, тому, що ви не пояснили зміст. Якщо ви все-таки поясніть це (у своїй відповіді), ви набагато частіше отримаєте більше голосів - і запитувач насправді щось дізнається!
Хлопець із капелюхом

2
Крім того, він повторює код із відповіді, яку я розмістив раніше, за винятком того, що він охоплює список розширень в операторі оцінки виразу масиву ( @()), що є зайвим, оскільки розділений комами список по суті оцінюється як масив.
Аді Інбар

-2

використовувати include - це найпростіший спосіб згідно

http://www.vistax64.com/powershell/168315-get-childitem-filter-files-multiple-extensions.html


1
Це не спрацювало. :( -filter -include *.file, *.types -filter -include (*.file, *.types), -filter -include "*.file", "*.types"і -filter -include ("*.file", "*.types")все помилковий, як на моє запитання вище Виключивши. -filterПараметр і тільки в тому числі -include( ті ж ітерації цитат і дужок) не призводять до час виконання помилок, але не було ніякого результуючого набору в каталозі призначення.
dwwilson66
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.