Объедините результаты двух разных вызовов Get-ChildItem в одну переменную, чтобы выполнить для них одинаковую обработку - PullRequest
18 голосов
/ 20 января 2011

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

Это то, что у меня есть:

$items = New-Object Collections.Generic.List[IO.FileInfo]

$loc1 = @(Get-ChildItem -Path "\\server\C$\Program Files (x86)\Data1\" -Recurse)
$loc2 = @(Get-ChildItem -Path "\\server\C$\Web\DataStorage\" -Recurse)

$items.Add($loc1) # This line fails (the next also fails)
$items.Add($loc2)

# Processing code is here

, которая завершается с этой ошибкой:

Невозможно преобразовать аргумент "0" со значением: "System.Object []", для "Добавить" для типа "System.IO.FileInfo": "Невозможно преобразовать" System.Object[] "тип типа" System.Object [] "для типа" System.IO.FileInfo "."

Меня больше всего интересует, каков правильный подход для ситуации такого типа.Я понимаю, что мой код - это очень C способ сделать это - если есть более PowerShell способ выполнить ту же задачу, я все для этого.Ключевым моментом является то, что число $loc#'s может меняться со временем, поэтому добавление и удаление одного или двух должно быть легко в результирующем коде.

Ответы [ 5 ]

28 голосов
/ 20 января 2011

Из get-help get-childitem: -Path Указывает путь к одному или нескольким местоположениям. Подстановочные знаки разрешены.Местом расположения по умолчанию является текущий каталог (.).

$items = get-childitem '\\server\C$\Program Files (x86)\Data1\','\\server\C$\Web\DataStorage\' -Recurse
24 голосов
/ 20 января 2011

Не уверен, что вам нужен общий список здесь. Вы можете просто использовать массив PowerShell, например ::100100

$items  = @(Get-ChildItem '\\server\C$\Program Files (x86)\Data1\' -r)
$items += @(Get-ChildItem '\\server\C$\Web\DataStorage\' -r)

Массивы PowerShell можно объединить с помощью +=.

5 голосов
/ 20 января 2011

Ответ Кейта - это способ PowerShell: просто используйте @ (...) + @ (...).

Если вам действительно нужен типобезопасный список [IO.FileInfo], тогда вам нужноиспользуйте AddRange и приведите массив объектов к массиву FileInfo - вам также нужно убедиться, что вы не получаете никаких объектов DirectoryInfo, иначе вам нужно использовать IO.FileSystemInfo в качестве типа списка:

, избегайте каталогов:

$items = New-Object Collections.Generic.List[IO.FileInfo]
$items.AddRange( ([IO.FileSystemInfo[]](ls '\\server\C$\Program Files (x86)\Data1\' -r | Where { -not $_.PSIsContainer } )) )
$items.AddRange( ([IO.FileSystemInfo[]](ls '\\server\C$\Web\DataStorage\' -r | Where { -not $_.PSIsContainer } )) )

Или используйте FileSystemInfo (общий базовый класс FileInfo и DirectoryInfo):

$items = New-Object Collections.Generic.List[IO.FileSystemInfo]
$items.AddRange( ([IO.FileSystemInfo[]](ls '\\server\C$\Program Files (x86)\Data1\' -r)) )
$items.AddRange( ([IO.FileSystemInfo[]](ls '\\server\C$\Web\DataStorage\' -r)) )
4 голосов
/ 20 января 2011

Вот, возможно, еще более мощный способ PowerShell, который не требует частичной конкатенации или явного добавления элементов к результату:

# Collect the results by two or more calls of Get-ChildItem
# and perhaps do some other job (but avoid unwanted output!)
$result = .{

    # Output items
    Get-ChildItem C:\TEMP\_100715_103408 -Recurse

    # Some other job
    $x = 1 + 1

    # Output some more items
    Get-ChildItem C:\TEMP\_100715_110341 -Recurse

    #...
}

# Process the result items
$result

Но код внутри блока скрипта должен быть написан немного более тщательно, чтобы избежать нежелательного вывода, смешанного с элементами файловой системы.

РЕДАКТИРОВАТЬ: В качестве альтернативы и, возможно, более эффективно, вместо .{ ... } мы можем используйте @( ... ) или $( ... ), где ... обозначает код, содержащий несколько звонки Get-ChildItem.

0 голосов
/ 28 ноября 2016

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

$files  = Get-ChildItem -Path "H:\stash\" -Filter *.rdlc -Recurse 
$files += Get-ChildItem -Path "H:\stash\" -Filter *.rdl  -Recurse 

Я сравнил вывод с таймером так:

$stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
# Do Stuff Here
$stopwatch.Stop()
Write-Host "$([Math]::Round($stopwatch.Elapsed.TotalSeconds)) seconds ellapsed"
...