수백만 개의 파일이 있는 폴더의 파일 크기와 파일 수를 찾기 위한 PowerShell 스크립트?
이 스크립트의 목적은 다음과 같습니다.
- 디렉터리에서 재귀적으로 찾은 파일 수 인쇄(폴더 자체 생략)
- 디렉터리의 총 합계 파일 크기 인쇄
- 메모리를 많이 사용하기 때문에 컴퓨터가 손상되지 않습니다.
지금까지 (3) 어려운 부분입니다.
여기 제가 지금까지 쓰고 테스트한 것이 있습니다.이것은 100개 또는 1000개의 파일이 있는 폴더에서 완벽하게 작동합니다.
$hostname=hostname
$directory = "foo"
$dteCurrentDate = Get-Date –f "yyyy/MM/dd"
$FolderItems = Get-ChildItem $directory -recurse
$Measurement = $FolderItems | Measure-Object -property length -sum
$colitems = $FolderItems | measure-Object -property length -sum
"$hostname;{0:N2}" -f ($colitems.sum / 1MB) + "MB;" + $Measurement.count + " files;" + "$dteCurrentDate"
그러나 수백만 개의 파일이 있는 폴더에서는$colitems
변수는 수백만 개의 파일의 정보 수집으로 인해 너무 방대해져서 시스템을 불안정하게 만듭니다.이 정보를 그리고 저장할 수 있는 더 효율적인 방법이 있습니까?
스트리밍 및 파이프라인을 사용하는 경우 (3) 문제를 많이 줄여야 합니다. 스트리밍할 때 각 개체가 사용 가능한 대로 파이프라인을 따라 전달되고 메모리를 많이 차지하지 않으므로 수백만 개의 파일을 처리할 수 있습니다(시간이 걸리더라도).
Get-ChildItem $directory -recurse | Measure-Object -property length -sum
저는 @Stej의 진술을 믿지 않습니다.Get-ChildItem probably reads all entries in the directory and then begins pushing them to the pipeline.
사실입니다.파이프라이닝은 PowerShell의 기본 개념입니다(cmdlet, 스크립트 등에서 지원).또한 처리된 개체가 사용 가능할 때와 필요할 때만 파이프라인을 따라 하나씩 전달되도록 합니다.Get-ChildItem
다르게 행동하지 않을 것입니다.
이에 대한 좋은 예는 Windows PowerShell 파이프라인 이해에 나와 있습니다.
여기서 인용하는 내용:
Out-Host -Paging 명령은 천천히 표시하려는 긴 출력이 있을 때마다 유용한 파이프라인 요소입니다.작업에 CPU가 많이 사용되는 경우 특히 유용합니다.표시할 수 있는 전체 페이지가 있을 때 처리가 Out-Host cmdlet으로 전송되므로 다음 출력 페이지를 사용할 수 있을 때까지 프로세스 앞에 있는 cmdlet이 파이프라인 작업을 중지합니다.윈도우즈 작업 관리자를 사용하여 윈도우즈 PowerShell에서 사용하는 CPU 및 메모리를 모니터링하는 경우 이를 볼 수 있습니다.
합니다.
Get-ChildItem C:\Windows -Recurse
및 합니다. CPU 및 메 명 비 교 합 니 다 과Get-ChildItem C:\Windows -Recurse | Out-Host -Paging
.
사용에 대한 벤치마크Get-ChildItem
에c:\
(백만 개는 아니지만 충분히 좋은 약 179516 파일):
실행 후 메모리 사용량$a = gci c:\ -recurse
(그리고 나서 하기$a.count
)이 있었습니다.527,332K
.
실행 후 메모리 사용량gci c:\ -recurse | measure-object
이었다59,452K
그리고 절대 위로 올라가지 않았습니다.80,000K
.
(Memory - Private Working Set - Task Manager에서 메모리 보기powershell.exe
과정.처음에, 그것은.22,000K
.)
저는 또한 2백만 개의 파일로 시도했습니다. (파일을 만드는 데 시간이 걸렸습니다!)
유사한 실험:
실행 후 메모리 사용량$a = gci c:\ -recurse
(그리고 나서 하기$a.count
)이 있었습니다.2,808,508K
.
실행 중 메모리 사용량gci c:\ -recurse | measure-object
이었다308,060K
그리고 절대 위로 올라가지 않았습니다.400,000K
그것이 끝난 후, 그것은 해야만 했습니다.[GC]::Collect()
그것이 다시 돌아오기 위해.22,000K
레벨
나는 여전히 확신합니다.Get-ChildItem
파이프라인을 사용하면 수백만 개의 파일에 대해서도 메모리를 크게 개선할 수 있습니다.
Get-ChildItem
디렉토리의 모든 항목을 읽은 다음 파이프라인으로 밀어넣기 시작합니다.그런 경우에는Get-ChildItem
잘 작동하지 않습니다. 로 전환해 보십시오.NET 4.0 및 사용EnumerateFiles
그리고.EnumeratedDirectories
:
function Get-HugeDirStats($directory) {
function go($dir, $stats)
{
foreach ($f in [system.io.Directory]::EnumerateFiles($dir))
{
$stats.Count++
$stats.Size += (New-Object io.FileInfo $f).Length
}
foreach ($d in [system.io.directory]::EnumerateDirectories($dir))
{
go $d $stats
}
}
$statistics = New-Object PsObject -Property @{Count = 0; Size = [long]0 }
go $directory $statistics
$statistics
}
#example
$stats = Get-HugeDirStats c:\windows
여기서 가장 비싼 부품은 다음과 같은 것입니다.New-Object io.FileInfo $f
,왜냐면EnumerateFiles
파일 이름만 반환합니다.따라서 파일 수만 충분하면 줄에 주석을 달 수 있습니다.
스택 오버플로 질문 PowerShell을 실행하는 방법을 참조하십시오.NET 4 런타임?사용법을 배우다NET 4.0.
또한 빠른 일반적인 오래된 방법을 사용할 수도 있지만 디렉토리의 모든 파일을 읽습니다.필요에 따라 다르니 한번 해보세요.나중에 모든 방법을 비교합니다.
function Get-HugeDirStats2($directory) {
function go($dir, $stats)
{
foreach ($f in $dir.GetFiles())
{
$stats.Count++
$stats.Size += $f.Length
}
foreach ($d in $dir.GetDirectories())
{
go $d $stats
}
}
$statistics = New-Object PsObject -Property @{Count = 0; Size = [long]0 }
go (new-object IO.DirectoryInfo $directory) $statistics
$statistics
}
비교:
Measure-Command { $stats = Get-HugeDirStats c:\windows }
Measure-Command { $stats = Get-HugeDirStats2 c:\windows }
Measure-Command { Get-ChildItem c:\windows -recurse | Measure-Object -property length -sum }
TotalSeconds : 64,2217378
...
TotalSeconds : 12,5851008
...
TotalSeconds : 20,4329362
...
@manojlds:파이프라이닝은 기본 개념입니다.그러나 개념적으로는 공급자와는 아무런 관련이 없습니다.파일 시스템 공급자는 에 의존합니다.NET 구현(.NET 2.0)에는 게으른 평가 기능(~ 열거자)이 없습니다.직접 확인해 보세요.
다음 기능은 폴더 크기를 계산하는 속도가 빠르고 매우 빠르지만 항상 작동하는 것은 아닙니다(특히 권한 문제가 있거나 폴더 경로가 너무 긴 경우).
Function sizeFolder($path) # Return the size in MB.
{
$objFSO = New-Object -com Scripting.FileSystemObject
("{0:N2}" -f (($objFSO.GetFolder($path).Size) / 1MB))
}
언급URL : https://stackoverflow.com/questions/7080654/a-powershell-script-to-find-the-file-size-and-file-count-of-a-folder-with-millio
'programing' 카테고리의 다른 글
Mac Excel 2011 VBA에서 Dir() 기능이 작동하지 않음 (0) | 2023.09.04 |
---|---|
Angular2: 사용자 지정 파이프를 찾을 수 없습니다. (0) | 2023.09.04 |
JQuery가 모든 Ajax 오류를 검색합니다. (0) | 2023.09.04 |
별도의 파일에 있는 db가 있는 mysqdump (0) | 2023.09.04 |
jDIV에 클래스 "x"가 없는 경우 쿼리 (0) | 2023.09.04 |