Когда у нас заканчивается место на диске, нам нужно знать, какие файлы нужно удалить, чтобы сэкономить место. В этой статье я поделюсь процессом создания функции для этого.
Чтобы просмотреть все файлы, мы используем Get-ChildItem
с параметром -File
. Для каждого объекта в возвращаемом списке мы можем получить доступ к его Length
, чтобы получить размер файла в байтах.
> Get-ChildItem -Path .\.git\ -File | >> ForEach-Object { Write-Host "$($_.Name): $($_.Length)" } COMMIT_EDITMSG: 81 config: 384 description: 73 FETCH_HEAD: 95 HEAD: 21 index: 352958 index.windows: 353147 ORIG_HEAD: 41 packed-refs: 9279
Используя суффиксы множителя KB,MB,GB
, мы можем преобразовать длину файла в удобочитаемые единицы.
> Get-ChildItem -Path .\.git\ -File | >> ForEach-Object { Write-Host "$($_.Name): $($_.Length/1GB)" } COMMIT_EDITMSG: 7.54371285438538E-08 config: 3.57627868652344E-07 description: 6.79865479469299E-08 FETCH_HEAD: 8.84756445884705E-08 HEAD: 1.9557774066925E-08 index: 0.00032871775329113 index.windows: 0.000328893773257732 ORIG_HEAD: 3.81842255592346E-08 packed-refs: 8.64174216985703E-06
Если размер файла слишком мал, преобразованное значение по-прежнему трудно прочитать. Поэтому мы можем использовать несколько единиц измерения для отображения размера файла.
Между тем, нам лучше округлить десятичные разряды в меньшую сторону.
> Get-ChildItem -Path .\.git\ -File | ForEach-Object { Write-Host "$($_.Name):$([Math]::Round($_.Length/1KB, 2))KB, $([Math]::Round($_.Length/1MB, 2))MB, $([Math]::Round($_.Length/1GB, 2))GB" } COMMIT_EDITMSG:0.08KB, 0MB, 0GB config:0.38KB, 0MB, 0GB description:0.07KB, 0MB, 0GB FETCH_HEAD:0.09KB, 0MB, 0GB HEAD:0.02KB, 0MB, 0GB index:344.69KB, 0.34MB, 0GB index.windows:344.87KB, 0.34MB, 0GB ORIG_HEAD:0.04KB, 0MB, 0GB packed-refs:9.06KB, 0.01MB, 0GB
Чтобы получить лучший формат вывода, мы можем использовать Select-Object
вместо ForEach-Object
. Команда Select-Object
может использовать ScriptBlock
для построения Property
— добавлять настраиваемое свойство (вычисляемое-свойство) по запросу. В этом примере мы хотим показать свойство Length
в единицах KB, MB, GB
.
Давайте посмотрим, как это сделать.
> Get-ChildItem -Path .\.git\ -File | >> Select-Object -Property Name, {[Math]::Round($_.Length/1KB, 2)}, {[Math]::Round($_.Length/1MB, 2)}, {[Math]::Round($_.Length/1GB, 2)} Name [Math]::Round($_.Length/1KB, 2) [Math]::Round($_.Length/1MB, 2) [Math]::Round($_.Length/1GB, 2) ---- ------------------------------- ------------------------------- ------------------------------- COMMIT_EDITMSG 0,08 0,00 0,00 config 0,38 0,00 0,00 description 0,07 0,00 0,00 FETCH_HEAD 0,09 0,00 0,00 HEAD 0,02 0,00 0,00 index 344,69 0,34 0,00 index.windows 344,87 0,34 0,00 ORIG_HEAD 0,04 0,00 0,00 packed-refs 9,06 0,01 0,00
Блок сценария {}
используется в качестве имени нового свойства. Чтобы сделать его более читабельным, нам нужно для него удобочитаемое имя свойства.
Для этого мы можем использовать хеш-таблицу: два ключа Label
и Expression
> Get-ChildItem -Path .\.git\ -File | >> Select-Object -Property Name ` >> ,@{Label='Size(KB)'; Expression={[Math]::Round($_.Length/1KB, 2)}} ` >> ,@{Label='Size(MB)'; Expression={[Math]::Round($_.Length/1MB, 2)}} ` >> ,@{Label='Size(GB)'; Expression={[Math]::Round($_.Length/1GB, 2)}} Name Size(KB) Size(MB) Size(GB) ---- -------- -------- -------- COMMIT_EDITMSG 0,08 0,00 0,00 config 0,38 0,00 0,00 description 0,07 0,00 0,00 FETCH_HEAD 0,09 0,00 0,00 HEAD 0,02 0,00 0,00 index 344,69 0,34 0,00 index.windows 344,87 0,34 0,00 ORIG_HEAD 0,04 0,00 0,00 packed-refs 9,06 0,01 0,00
Теперь он выглядит намного лучше.
📓 Label
может быть и Name
. (Я не знаю, можно ли использовать другое строковое значение)
Следующей интересной вещью должна быть сортировка результата, чтобы показать самые большие файлы в верхней позиции — это то, что мы хотим сделать в начале.
Мы используем команду Sort-Object
.
> Get-ChildItem -Path .\.git\ -File | >> Select-Object -Property Name ` >> ,@{Label='Size(KB)'; Expression={[Math]::Round($_.Length/1KB, 2)}} ` >> ,@{Label='Size(MB)'; Expression={[Math]::Round($_.Length/1MB, 2)}} ` >> ,@{Label='Size(GB)'; Expression={[Math]::Round($_.Length/1GB, 2)}} | >> Sort-Object { $_."Size(KB)" } -Descending Name Size(KB) Size(MB) Size(GB) ---- -------- -------- -------- index.windows 344,87 0,34 0,00 index 344,69 0,34 0,00 packed-refs 9,06 0,01 0,00 config 0,38 0,00 0,00 FETCH_HEAD 0,09 0,00 0,00 COMMIT_EDITMSG 0,08 0,00 0,00 description 0,07 0,00 0,00 ORIG_HEAD 0,04 0,00 0,00 HEAD 0,02 0,00 0,00
Когда мы рекурсивно проверяем весь том, например C:\
, возвращаемых файлов будет слишком много для отображения, и тогда мы можем ограничить общее количество в списке.
Мы используем команду Select-Object
с параметром -First
.
> Get-ChildItem -Path 'C:\' -Recurse -File | >> Select-Object -Property FullName ` >> ,@{Label='Size(KB)'; Expression={[Math]::Round($_.Length/1KB, 2)}} ` >> ,@{Label='Size(MB)'; Expression={[Math]::Round($_.Length/1MB, 2)}} ` >> ,@{Label='Size(GB)'; Expression={[Math]::Round($_.Length/1GB, 2)}} | >> Sort-Object { $_."Size(KB)" } -Descending | >> Select-Object -First 5 Name Size(KB) Size(MB) Size(GB) ---- -------- -------- -------- C:\...\IxNetwork-2018-11-15-09-38-33-P20816.dmp 2040997,07 1993,16 1,95 C:\...\IMG_1395.MOV 1296185,29 1265,81 1,24 C:\...\en_lzn7604002_r5a.alx 1262491,46 1232,90 1,20 C:\...\Noto-unhinted.zip 1088438,54 1062,93 1,04 C:\...\20220422_143651000_iOS.mp4 831227,84 811,75 0,79
📓 Здесь мы используем FullName
, чтобы показать абсолютные пути к файлам результатов, чтобы знать, где именно они находятся. Я просто скрываю путь под ...
, который на самом деле не является реальным результатом команды.
Мы также можем использовать Where-Object
для фильтрации тех файлов, размер которых больше заданного порогового значения, например 1GB
.
> Get-ChildItem -Path 'C:\' -Recurse -File | >> Select-Object -Property Name ` >> ,@{Label='Size(KB)'; Expression={[Math]::Round($_.Length/1KB, 2)}} ` >> ,@{Label='Size(MB)'; Expression={[Math]::Round($_.Length/1MB, 2)}} ` >> ,@{Label='Size(GB)'; Expression={[Math]::Round($_.Length/1GB, 2)}} | >> Sort-Object { $_."Size(KB)" } -Descending | >> Where-Object { $_."Size(GB)" -ge 1 } Name Size(KB) Size(MB) Size(GB) ---- -------- -------- -------- C:\...\IxNetwork-2018-11-15-09-38-33-P20816.dmp 2040997,07 1993,16 1,95 C:\...\IMG_1395.MOV 1296185,29 1265,81 1,24 C:\...\en_lzn7604002_r5a.alx 1262491,46 1232,90 1,20 C:\...\Noto-unhinted.zip 1088438,54 1062,93 1,04
📓 Мы используем -ge 1
вместо -ge 1GB
выше в столбце «Размер (ГБ)», поскольку мы уже преобразовали Length
из байтов в GB
.
Однако, чтобы сделать его более гибким, мы можем использовать исходное значение Length
для фильтрации — мы можем использовать любое значение с суффиксами множителя для фильтрации.
> Get-ChildItem -Path '.\.git\' -Recurse -File | >> Select-Object -Property Name, Length ` >> ,@{Label='Size(KB)'; Expression={[Math]::Round($_.Length/1KB, 2)}} ` >> ,@{Label='Size(MB)'; Expression={[Math]::Round($_.Length/1MB, 2)}} ` >> ,@{Label='Size(GB)'; Expression={[Math]::Round($_.Length/1GB, 2)}} | >> Where-Object { $_.Length -ge 10MB } | >> Sort-Object { $_."Size(KB)" } -Descending | Select-Object -First 10 | >> Format-Table Name Length Size(KB) Size(MB) Size(GB) ---- ------ -------- -------- -------- dbb48e5c36dcdc708b5935a885bb30687431a7 115862011 113146,50 110,49 0,11 pack-d6844473eef0db2aa2ac0a8c3933f3c6716fa798.pack 33116617 32340,45 31,58 0,03 > Get-ChildItem -Path '.\.git\' -Recurse -File | >> Select-Object -Property Name, Length ` >> ,@{Label='Size(KB)'; Expression={[Math]::Round($_.Length/1KB, 2)}} ` >> ,@{Label='Size(MB)'; Expression={[Math]::Round($_.Length/1MB, 2)}} ` >> ,@{Label='Size(GB)'; Expression={[Math]::Round($_.Length/1GB, 2)}} | >> Where-Object { $_.Length -ge 200KB } | >> Sort-Object { $_."Size(KB)" } -Descending | Select-Object -First 10 | Format-Table Name Length Size(KB) Size(MB) Size(GB) ---- ------ -------- -------- -------- dbb48e5c36dcdc708b5935a885bb30687431a7 115862011 113146,50 110,49 0,11 pack-d6844473eef0db2aa2ac0a8c3933f3c6716fa798.pack 33116617 32340,45 31,58 0,03 pack-d6844473eef0db2aa2ac0a8c3933f3c6716fa798.idx 1603624 1566,04 1,53 0,00 2703fe3cbc651d7541e17f3885b5eec2d4c643 394368 385,12 0,38 0,00 index.windows 353147 344,87 0,34 0,00 index 352958 344,69 0,34 0,00
📓 Чтобы использовать Length
в качестве столбца фильтрации, нам нужно добавить Length
в список -Property
.
Кроме того, мы можем использовать Out-GridView
для отображения списка результатов в интерактивном окне.
> Get-ChildItem -Path '.\.git\' -Recurse -File | >> Select-Object -Property Name, Length ` >> ,@{Label='Size(KB)'; Expression={[Math]::Round($_.Length/1KB, 2)}} ` >> ,@{Label='Size(MB)'; Expression={[Math]::Round($_.Length/1MB, 2)}} ` >> ,@{Label='Size(GB)'; Expression={[Math]::Round($_.Length/1GB, 2)}} | >> Where-Object { $_.Length -ge 200KB } | >> Sort-Object { $_."Size(KB)" } -Descending | Select-Object -First 10 | >> Out-GridView
В интерактивном окне Out-GridView мы можем динамически сортировать и фильтровать список результатов. Это очень полезно для длинного списка результатов.
Наконец, мы можем поместить все коды в функцию для повторного использования.
<# .SYNOPSIS Find big files in the given path. .DESCRIPTION Find files in the given path, sort by size and return top ones. .PARAMETER Path The target path where to find big files. .PARAMETER Threshould The size threshould for found result files. .PARAMETER First How many top big files to show and return. .PARAMETER ShowByGridView $true to show result in gridview, $false to show in console by table. .EXAMPLE Find-BigFiles -Path "C:\Users\wenijinew" -First 20 .EXAMPLE Find-BigFiles -Path "C:\Users\wenijinew" -Threshould 100MB .EXAMPLE Find-BigFiles -Path "C:\Users\wenijinew" -Threshould 1GB -ShowByGridView $true #> Function Find-BigFiles($Path, $Threshould=$null, $First=10, $ShowByGridView=$false){ $Files = Get-ChildItem -Path $Path -Recurse -Force -File | Select-Object -Property FullName, Length ` ,@{Name='Size(GB)';Expression={[Math]::Round($_.Length / 1GB, 2)}} ` ,@{Name='Size(MB)';Expression={[Math]::Round($_.Length / 1MB, 2)}} ` ,@{Name='Size(KB)';Expression={[Math]::Round($_.Length / 1KB, 2)}} if ($Threshould -ne $null){ $Files = $Files | Where-Object { $_.Length -ge $Threshould } } $Files = $Files | Sort-Object { $_.Length } -Descending | Select-Object -First $First if ($ShowByGridView -eq $true){ $Files | Out-GridView }else{ $Files | Format-Table } return $Files }
Заворачивать
В этой статье мы реализуем одну функцию для пошагового поиска больших файлов. Он охватывает следующие функции и знакомит с использованием нескольких комлетов.
- Получите доступ к размеру файлов на
Length
объектов, возвращенныхGet-ChildItem
- Преобразование
Length
единиц из байтов вKB, MB, GB
- Создайте настроенное свойство путем вычисления исходного свойства —
Length
файлового объекта. - Фильтровать объекты по
Where-Object
- Сортировать объекты по
Sort-Object
- Вернуть первые
n
объектов по-First
изSelect-Object
- Используйте
Format-Table
для форматирования свойств объектов - Используйте
Out-GridView
для отображения вывода в интерактивном окне, где поддерживаются динамическая сортировка и фильтрация.
Надеюсь, это поможет вам в изучении PowerShell и повседневной работе, связанной с экономией больших файлов и дискового пространства.
Рекомендации
- [1] Select-Object: Пример 11: Создание вычисляемых свойств для каждого InputObject
- [2] Целые литералы
- [3] Вне сетки