Как правильно фильтровать несколько строк в сценарии копирования 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?

Так что я делаю не так и как это исправить?

dwwilson66
источник

Ответы:

194

-Filter принимает только одну строку. -Include принимает несколько значений, но квалифицирует аргумент -Path . Хитрость заключается в том, чтобы добавить \*в конец пути, а затем использовать -Include для выбора нескольких расширений. Кстати, цитирование строк в аргументах командлета не требуется, если они не содержат пробелы или специальные символы оболочки.

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

Обратите внимание, что это будет работать независимо от того, заканчивается ли $ originalPath обратной косой чертой, поскольку несколько последовательных обратных косых черт интерпретируются как один разделитель пути. Например, попробуйте:

Get-ChildItem C:\\\\\Windows
Ади Инбар
источник
5
Вуху! Этот \*трюк только что решил около шести проблем. Отлично и спасибо!
dwwilson66 05
17
Обратите внимание, что подстановочный знак ( \*) не требуется, если -Recurseон указан.
Охад Шнайдер
почему-то это не работает при поиске каталогов?
Росс Прессер
Добавление -Recurse позволяет обращаться к подпапкам
Дерек
2

Что-то вроде этого должно сработать (у меня это сработало). Причина, по которой вы хотите использовать -Filterвместо, -Includeзаключается в том, что 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 за один раз, чем сделать -filter * .png и объединить результаты, чем сделай один -Include *.jpg, *.png". У меня есть папка, содержащая 126k файлов и 18k папок. Я рекурсивно ищу один файл и одну папку в каждой папке. использование -Filter занимает 5 секунд, а использование -Include 30 секунд. Выполнение -Filter два раза за 10 секунд в три раза быстрее, чем одно -Include go.
papo
0
Get-ChildItem $originalPath\* -Include @("*.gif", "*.jpg", "*.xls*", "*.doc*", "*.pdf*", "*.wav*", "*.ppt")
ЦОД
источник
Добро пожаловать в Stack Overflow! Этот ответ оказался в очереди на проверку низкого качества, предположительно из-за того, что вы не объяснили содержание. Если вы объясните это (в своем ответе), у вас гораздо больше шансов получить больше голосов - и спрашивающий действительно что-то узнает!
Парень в шляпе
2
Кроме того, он повторяет код из ответа, который я опубликовал ранее, за исключением того, что он включает список расширений в оператор оценки выражения массива ( @()), что является излишним, поскольку список, разделенный запятыми, по своей сути оценивается как массив.
Ади Инбар
-2

использовать включение - это самый простой способ согласно

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