Измерьте несколько свойств?
Я хотел бы запросить каталог с помощью Get-ChildItem и создать таблицу со столбцами, такими как Path, Size(в ГБ), MinimumCreationTime, MaximumCreationTime. В цикле foreach я написал 3 команды измерения. Возможно ли измерить несколько свойств с помощью одной команды?
$pathes = @'
C:\open
C:\games
'@.Split([System.Environment]::NewLine, [System.StringSplitOptions]::RemoveEmptyEntries)
foreach ($path in $pathes){
Get-ChildItem $path -Recurse | Measure Length -Sum
Get-ChildItem $path -Recurse | Measure CreationTime -Minimum
Get-ChildItem $path -Recurse | Measure CreationTime -Maximum
}
2 ответа
Возможно ли измерить несколько свойств с помощью одной команды?
Да, можно - только не так, как вам нужно .
Причина, по которой мы не можем полностью консолидировать здесь все три вызова, заключается в том, что они будут выполнять все запрошенные вычисления для каждого входного свойства - и он не может осмысленно вычислить сумму нескольких
Так что в лучшем случае мы можем сделать это, используя всего 2 витка трубопровода, чтобы
$paths = 'C:\open','C:\games'
foreach ($path in $paths){
# Let's call Get-ChildItem ONCE, and store the result
$children = Get-ChildItem $path -Recurse
# Now let's do our calculations
$fileSize = $children | Measure Length -Sum
$newAndOld = $children | Measure CreationTime -Minimum -Maximum
# And finally create a new object to hold the details we calculated above
[pscustomobject]@{
Path = $path
TotalSize = $fileSize.Sum
OldestFileTime = $newAndOld.Minimum
NewestFileTime = $newAndOld.Maximum
}
}
PowerShell по умолчанию будет использовать табличный формат при отображении объектов с 4 или менее свойствами, поэтому вы можете ожидать, что вывод по умолчанию в оболочке будет примерно таким (в зависимости от языкового стандарта):
Path TotalSize OldestFileTime NewestFileTime
---- --------- -------------- --------------
C:\open 1234567890 1/1/2018 2:00:00 AM 1/31/2021 7:45:00 PM
C:\games 1234567890 1/1/2018 2:00:00 AM 1/31/2021 7:45:00 PM
Это возможно с помощью одного вызова команды с использованием вычисляемого свойства, которое преобразует свойство в числовой тип. Сейчас же
-Sum
с этим можно работать (правда, за эту сумму отбросим).
После того, как мы рассчитали статистику, мы конвертируем обратно в, чтобы получить значимые отображаемые значения.
Начиная с PS 7+, вычисляемое свойство можно использовать в качестве аргумента. Для более старых версий PS мы можем использовать для создания вычисляемого свойства.
Решение PS 7+
foreach ($path in $pathes){
$stats = Get-ChildItem $path -File -Recurse |
Measure-Object 'Length', { $_.CreationTime.Ticks } -Sum -Minimum -Maximum
# Create the output for one table row
[PSCustomObject]@{
Path = $path
'Size(GB)' = [math]::Round( $stats[0].Sum / 1GB, 2 ) # 2 = number of digits
MinimumCreationTime = [DateTime] [Int64] $stats[1].Minimum
MaximumCreationTime = [DateTime] [Int64] $stats[1].Maximum
}
}
Объяснение:
- Мы указываем два свойства в вызове:
- 1-й объект недвижимости просто
- 2-е свойство - это
вычисляемое свойство , то есть оно получает свое значение при запуске небольшого блока скрипта. Блок скрипта преобразует в Int64
и использует его как значение, которое будет измеряться.
- При указании нескольких свойств для он выводит массив, содержащий объект для каждого свойства, который содержит статистику.
-
$stats[0]
содержит, а дляLength
собственность, из которой мы только берем. -
$stats[1]
содержитSum
, а дляCreationTime
собственность, из которой мы берем толькоMinimum
иMaximum
. Обратите внимание, что производит вывод типа[double]
, поэтому сначала нам нужно преобразовать обратно в[Int64]
прежде чем окончательно преобразовать обратно в[DateTime]
.
-
Решение PS 5
foreach ($path in $pathes){
$stats = Get-ChildItem $path -File -Force |
Select-Object Length, @{ name = 'CreationTimeTicks'; expression = { $_.CreationTime.Ticks } } |
Measure-Object Length, CreationTimeTicks -Sum -Minimum -Maximum
# Create the output for one table row - identical to PS 7+ solution
[PSCustomObject]@{
Path = $path
'Size(GB)' = [math]::Round( $stats[0].Sum / 1GB, 2 ) # 2 = number of digits
MinimumCreationTime = [DateTime] [Int64] $stats[1].Minimum
MaximumCreationTime = [DateTime] [Int64] $stats[1].Maximum
}
}
Объяснение:
Это похоже на решение для PS 7+, за исключением того, что мы используем
Select-Object
для создания вычисляемого свойства с именем
CreationTimeTicks
, поэтому мы можем передать его по имени в
Measure-Object
вызов.
Вывод
Хотя этот код, похоже, работает, код, представленный этим ответом , концептуально намного понятнее, поэтому я бы пошел с ним.