programing

서로 다른 두 Get-ChildItem 호출의 결과를 단일 변수로 결합하여 동일한 처리를 수행합니다.

yellowcard 2023. 8. 13. 09:38
반응형

서로 다른 두 Get-ChildItem 호출의 결과를 단일 변수로 결합하여 동일한 처리를 수행합니다.

여러 디렉터리에서 파일 목록을 만들기 위해 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" 인수를 변환할 수 없습니다.개체[], "시스템" 유형에 "추가"를 지정합니다.IO.FileInfo": "시스템을 변환할 수 없습니다."System" 유형의 Object[] 값입니다.개체[]에서 "시스템"을 입력합니다.IO.FileInfo".

저는 이러한 상황에 대한 올바른 접근법이 무엇인지에 대해 대부분 관심이 있습니다.저는 제 코드가 매우 C적인 방법이라는 것을 알고 있습니다. 만약 PowerShell이 동일한 작업을 수행할 수 있는 더 많은 방법이 있다면, 저는 전적으로 찬성합니다.중요한 것은, 그 숫자가 하는 것입니다.$loc#'s시간이 지남에 따라 변경될 수 있으므로 결과 코드에서 하나 또는 둘을 추가하고 제거하는 것이 쉬울 것입니다.

여기에 일반 목록이 필요한지 확실하지 않습니다.PowerShell 어레이만 사용할 수 있습니다. 예:

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

PowerShell 어레이는 다음을 사용하여 연결할 수 있습니다.+=.

From get-help get-child item: -Path 하나 이상의 위치에 대한 경로를 지정합니다.와일드카드가 허용됩니다.기본 위치는 현재 디렉터리(.)입니다.

$items = get-childitem '\\server\C$\Program Files (x86)\Data1\','\\server\C$\Web\DataStorage\' -Recurse

다음은 부품 연결이나 명시적으로 항목을 결과에 추가할 필요가 전혀 없는 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.

Keith의 대답은 PowerShell 방식입니다. 그냥 @(...)+@(...)를 사용하십시오.

실제로 유형 안전 목록을 원한다면 [IO.FileInfo], 그런 다음 AddRange를 사용하고 객체 배열을 FileInfo 배열에 캐스트해야 합니다. 또한 디렉터리가 없는지 확인해야 합니다.개체에 정보를 제공하거나 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)) )

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

언급URL : https://stackoverflow.com/questions/4749979/combine-the-results-of-two-distinct-get-childitem-calls-into-single-variable-to

반응형