Рекурсивно посчитать файлы в подпапках
Я пытаюсь подсчитать файлы во всех подпапках в каталоге и отобразить их в списке.
например следующее dirtree:
TEST
/VOL01
file.txt
file.pic
/VOL02
/VOL0201
file.nu
/VOL020101
file.jpg
file.erp
file.gif
/VOL03
/VOL0301
file.org
должно дать как выход:
PS> DirX C:TEST
Directory Count
----------------------------
VOL01 2
VOL02 0
VOL02/VOL0201 1
VOL02/VOL0201/VOL020101 3
VOL03 0
VOL03/VOL0301 1
Я начал со следующего:
Function DirX($directory)
{
foreach ($file in Get-ChildItem $directory -Recurse)
{
Write-Host $file
}
}
Теперь у меня вопрос: почему моя функция не рекурсией?
6 ответов
что-то вроде этого должно работать:
dir -recurse | ?{ $_.PSIsContainer } | %{ Write-Host $_.FullName (dir $_.FullName | Measure-Object).Count }
-
dir -recurse
перечисляет все файлы в текущем каталоге и трубах ( | ) результат в -
?{ $_.PSIsContainer }
который фильтрует каталоги только затем снова передает результирующий список в -
%{ Write-Host $_.FullName (dir $_.FullName | Measure-Object).Count }
который является циклом foreach, который для каждого члена списка ( $ _ ) отображает полное имя и результат следующего выражения (dir $_.FullName | Measure-Object).Count
который предоставляет список файлов под $_.FullName путь и подсчет членов через Измерения-Объект?{ ... }
- псевдоним для Where-Object-
%{ ... }
- это псевдоним для foreach
подобно решению Дэвида, это будет работать в Powershell v3.0 и не использует псевдонимы в случае, если кто-то не знаком с ними
Get-ChildItem -Directory | ForEach-Object { Write-Host $_.FullName $(Get-ChildItem $_ | Measure-Object).Count}
Ответ Дополнение
основываясь на комментарии о сохранении вашей функции и структуры цикла, я предоставляю следующее. Примечание: Я не одобряю это решение, поскольку оно уродливо, и встроенные командлеты справляются с этим очень хорошо. Однако мне нравится помогать, поэтому вот обновление вашего скрипт.
Function DirX($directory)
{
$output = @{}
foreach ($singleDirectory in (Get-ChildItem $directory -Recurse -Directory))
{
$count = 0
foreach($singleFile in Get-ChildItem $singleDirectory.FullName)
{
$count++
}
$output.Add($singleDirectory.FullName,$count)
}
$output | Out-String
}
для каждого $singleDirectory
подсчитайте все файлы с помощью $count
(который сбрасывается до следующего цикла sub) и выводит каждый поиск в хэш-таблицу. В конце выведите hashtable в виде строки. В вашем вопросе вы выглядели так, как будто вам нужен вывод объекта вместо прямого текста.
Ну, то, как вы это делаете все Get-ChildItem
командлет должен быть завершен до foreach
цикл может начать итерацию. Ты уверен, что ждешь достаточно долго? Если вы запустите это против очень больших каталогов (например, C:), это займет довольно много времени.
Edit: видел, что вы просили ранее способ заставить вашу функцию делать то, что вы просите, вот вы идете.
Function DirX($directory)
{
foreach ($file in Get-ChildItem $directory -Recurse -Directory )
{
[pscustomobject] @{
'Directory' = $File.FullName
'Count' = (GCI $File.FullName -Recurse).Count
}
}
}
DirX D:\
цикл foreach только получает каталоги, так как это все, о чем мы заботимся, а затем внутри цикл пользовательский объект создается для каждой итерации с полным путем к папке и количеством элементов внутри папки.
кроме того, обратите внимание, что это будет работать только в PowerShell 3.0 или новее, поскольку -directory
параметр не существовал в 2.0
моя версия-немного чище и сбрасывает содержимое в файл
Оригинал - рекурсивно подсчитывать файлы в подпапках
Вторая Составляющая - подсчет элементов в папке с PowerShell
$FOLDER_ROOT = "F:\"
$OUTPUT_LOCATION = "F:DLS\OUT.txt"
Function DirX($directory)
{
Remove-Item $OUTPUT_LOCATION
foreach ($singleDirectory in (Get-ChildItem $directory -Recurse -Directory))
{
$count = Get-ChildItem $singleDirectory.FullName -File | Measure-Object | %{$_.Count}
$summary = $singleDirectory.FullName+" "+$count+" "+$singleDirectory.LastAccessTime
Add-Content $OUTPUT_LOCATION $summary
}
}
DirX($FOLDER_ROOT)
Я немного изменил решение Дэвида Брабанта, чтобы оценить результат:
$FileCounter=gci "$BaseDir" -recurse | ?{ $_.PSIsContainer } | %{ (gci "$($_.FullName)" | Measure-Object).Count }
Write-Host "File Count=$FileCounter"
If($FileCounter -gt 0) {
... take some action...
}
Get-ChildItem $rootFolder `
-Recurse -Directory |
Select-Object `
FullName, `
@{Name="FileCount";Expression={(Get-ChildItem $_ -File |
Measure-Object).Count }}