Практические команды PowerShell — мелкие приёмы для повседневной работы

· Обновлено: · · PowerShell, Windows, Командная строка, Автоматизация, Повышение эффективности, Использование существующих активов

История изменений (1 обновлений, последнее 30 Aug 2026)

Журнал изменений этой статьи. Там, где версия до правки была заархивирована, она остаётся доступной для чтения по постоянной ссылке с DOI.

Русский текст переписан как полноценный технический перевод, а не калька с японского. Утверждения статьи не менялись.
Первая публикация
Цитирование статьи(DOI (зарегистрированный архив): 10.5281/zenodo.21619869)

Приведённые ниже DOI относятся к ранее зарегистрированным архивным версиям, которые могут отличаться от текущего текста. Для ссылки на текущий текст используйте URL этой страницы.

Го Комура (2026). Практические команды PowerShell — мелкие приёмы для повседневной работы. KomuraSoft LLC. https://comcomponent.com/ru/blog/2026/06/02/002-powershell-practical-command-recipes/

DOI (зарегистрированный архив)
10.5281/zenodo.21619869
DOI (последняя зарегистрированная версия)
10.5281/zenodo.21619870

1. Что стоит понять в первую очередь

Освоив основы PowerShell, дальше имеет смысл наращивать набор мелких приёмов, которые часто нужны в работе, — тогда повседневные задачи решаются проще.

«Мелкие приёмы» здесь — не короткие псевдонимы. В этой статье вместо сокращений вроде ls и cat используются полные имена командлетов: Get-ChildItem, Get-Content, Select-String.

На этой основе следующие задачи должны получаться одной или несколькими строками:

Посчитать количество
Узнать суммарный размер
Убрать дубликаты
Сгруппировать по типам
Достать только нужные значения
Сравнить два набора результатов
Посмотреть строки вокруг найденной в логе
Отправить результат в буфер обмена
Сохранить вывод и одновременно показать его на экране
Проверить переменные окружения и сеть

PowerShell полезен и без длинных скриптов. Сначала расширьте набор часто используемых блоков, чтобы в повседневной работе их можно было понемногу комбинировать.

Важнее не зубрить команды, а в нужный момент вспоминать: «для этой задачи подходит вот этот блок».

Код из статьи опубликован на GitHub как готовый к запуску набор примеров, разложенный по темам в соответствии с главами (скрипты-рецепты и тесты Pester).

powershell-practical-command-recipes - komurasoft-blog-samples (GitHub)

Чем эта статья отличается от предыдущей

Эта статья продолжает Основы команд PowerShell — операции, которые стоит выучить первыми, и как использовать их безопасно. Роли разделены так:

  Основы команд PowerShell Эта статья
Цель Начать работать в PowerShell Научиться считать, группировать, сравнивать извлечённые результаты и сохранять их
В центре Синтаксис и конвейер, поиск команд Блоки для подсчёта, сравнения, выборки и вывода
CSV / JSON Базовое чтение и запись Фильтрация уже загруженных данных и их агрегация
Процессы / службы / журнал событий Как получить список Как посчитать полученный список по типам и снять разницу
Изменяющие команды Сам безопасный порядок выполнения Команды разбора и сохранения копий, которые встраиваются в этот порядок

Короче: предыдущая статья доводит до «как достать значения», эта — «что с ними делать дальше».

Основы команд получения вроде Get-ChildItem, Get-Content, Import-Csv, Get-Service, политика выполнения, написание .ps1 и обработка ошибок — в предыдущей статье. Здесь мы на это опираемся и идём дальше. Темы вроде «Format-* ставить в конец» и Export-Csv -Encoding UTF8 встречаются в обеих статьях, но здесь они рассматриваются под углом «как подготовить данные к подсчёту и сравнению».

На схеме сплошная линия обозначает отношение, которое выполняется всегда, а пунктирная — условное отношение (условия указаны в пояснении к каждому отношению на странице сведений). Полный список отношений (всего 26, с доказательствами и степенью уверенности) и определения основных понятий собраны на странице сведений карты знаний (на японском). Данные: JSON-LD / Turtle

2. Подход в этой статье

Три исходные предпосылки:

  1. Команды писать полными именами
  2. Опираться в основном на команды, которые только читают данные
  3. Изменяющие команды всегда рассматривать вместе с проверкой объектов и -WhatIf

Например, безопаснее не учить сразу команду удаления файлов, а сначала освоить такой порядок:

Посмотреть объекты
  → отфильтровать по условию
  → посчитать
  → при необходимости сохранить в CSV
  → проверить, что именно изменится
  → выполнить

В этой статье в центре не сильные операции вроде удаления и остановки, а разбор, подсчёт, сравнение и вывод.

3. Карта часто используемых команд

Основные команды, которые понадобятся. В правом столбце — главы, где они разбираются подробнее.

Что нужно сделать Команда Глава
Посчитать количество или сумму Measure-Object 4, 5
Достать только нужные значения Select-Object -ExpandProperty 6
Убрать дубликаты Sort-Object -Unique 7
Сгруппировать по типам Group-Object 8
Вывести нужные столбцы и добавить вычисляемые Select-Object 9
Отсортировать Sort-Object 10
Искать строки Select-String 12
Сравнить два набора результатов Compare-Object 14
Посчитать хеш Get-FileHash 15
Работать с буфером обмена Set-Clipboard / Get-Clipboard 16
Вывести и на экран, и в файл Tee-Object 17
Сохранить журнал работы Start-Transcript 18
Проверить сетевую доступность Test-Connection / Test-NetConnection 26
Измерить время выполнения Measure-Command 28
Посмотреть детали ошибки Get-Error 31
Обработать каждый элемент ForEach-Object по ходу глав

Учить всё сразу не нужно. Удобнее запоминать в паре с целью: «посчитать — Measure-Object», «сгруппировать — Group-Object», «сравнить — Compare-Object».

Карта глав по задачам

Главы с 4-й по 36-ю сгруппированы так. Можно начинать с нужного места.

Категория Главы О чём речь
Подсчёт и подготовка вывода 4–11 Количество, сумма, максимум и среднее, выборка значений, удаление дубликатов, группировка по типам, вычисляемые столбцы, сортировка, место Format-*
Текст и разбор логов 12–14 Поиск строк и соседний контекст, замена, сравнение двух списков
Содержимое файлов и данных 15, 19, 20 Проверка хеша, фильтрация CSV, значения в JSON
Вывод и копии для отчёта 16–18 Буфер обмена, одновременный вывод на экран и в файл, журнал работы
Разбор системы 21–25, 31 Переменные окружения, профиль, процессы, службы, журнал событий, детали ошибок
Сеть 26, 27 Проверка доступности, ответы Web
Как выполнять 28–30 Замер времени, фоновый запуск, история команд
Напоминание по синтаксису 32 Операторы сравнения
Готовые рецепты 33, 34 11 рабочих рецептов и оговорки при сочетании с изменяющими командами
Шпаргалка 35 Таблица, чтобы вспоминать команду по задаче

Если задача ясна, а команда не вспоминается, быстрее всего начать со шпаргалки в главе 35.

4. Посчитать количество — Measure-Object

Самая частая операция — посчитать количество.

Число файлов в текущей папке:

Get-ChildItem . -File | Measure-Object

Чтобы захватить и вложенные папки:

Get-ChildItem . -File -Recurse | Measure-Object

Count в результате Measure-Object — это и есть количество.

Чтобы увидеть суммарный размер файлов, агрегируйте Length.

Get-ChildItem . -File -Recurse |
  Measure-Object -Property Length -Sum

В таком виде это байты, человеку читать неудобно, поэтому переведём в гигабайты.

$size = Get-ChildItem . -File -Recurse |
  Measure-Object -Property Length -Sum

[math]::Round($size.Sum / 1GB, 2)

Так удобно примерно оценить размер папки целиком.

5. Заодно смотрим максимум и среднее

Measure-Object умеет не только сумму, но и максимум со средним.

Get-ChildItem . -File |
  Measure-Object -Property Length -Sum -Average -Maximum -Minimum

Так смотрят разброс размеров файлов.

Можно просуммировать и накопительное процессорное время процессов. Свойство CPU у Get-Process — это не текущая загрузка, а число секунд процессорного времени с момента запуска процесса.

Get-Process |
  Measure-Object -Property CPU -Sum

Это накопительное значение, а не мгновенная загрузка CPU, поэтому оно зависит от момента запуска команды и от того, как долго процессы уже работают.

Для разбора этого достаточно. Для строгого мониторинга нужны отдельные средства наблюдения и продуманная схема журналирования.

6. Достать только значения — Select-Object -ExpandProperty

Select-Object чаще всего используют, чтобы выбрать столбцы.

Get-Process |
  Select-Object Name, Id, CPU

Это даёт «объекты со столбцами Name, Id и CPU».

Если нужны только значения, используйте -ExpandProperty.

Get-Process -Name notepad -ErrorAction SilentlyContinue |
  Select-Object -ExpandProperty Id

То же самое, когда нужны только имена файлов.

Get-ChildItem . -File |
  Select-Object -ExpandProperty Name

Когда результат команды нужно передать другой команде или в текстовый файл, -ExpandProperty удобен.

Например, сохраним только список имён файлов.

Get-ChildItem . -File |
  Select-Object -ExpandProperty Name |
  Set-Content .\file-names.txt -Encoding UTF8

Select-Object Name и Select-Object -ExpandProperty Name похожи, но форма результата разная.

Select-Object Name
  → таблица со столбцом Name

Select-Object -ExpandProperty Name
  → сами значения Name

Если результат уходит в CSV, лучше оставить столбец. Если его нужно передать в дальнейшую обработку строк — удобнее просто значения.

7. Убрать дубликаты — Sort-Object -Unique

Допустим, нужен список только расширений файлов.

Get-ChildItem . -File |
  Select-Object -ExpandProperty Extension |
  Sort-Object -Unique

На выходе останутся только уникальные расширения, например .txt, .log, .csv.

Так же можно посмотреть только уникальные имена процессов.

Get-Process |
  Select-Object -ExpandProperty ProcessName |
  Sort-Object -Unique

Пример: из CSV со списком пользователей достать только названия отделов.

Import-Csv .\users.csv |
  Select-Object -ExpandProperty Department |
  Sort-Object -Unique

Когда в списке много одинаковых значений и читать его тяжело, первым делом вспоминайте Sort-Object -Unique.

8. Сгруппировать по типам — Group-Object

Если нужно не просто убрать дубликаты, а увидеть «чего сколько», используйте Group-Object.

Посчитаем файлы по расширениям.

Get-ChildItem . -File |
  Group-Object -Property Extension -NoElement |
  Sort-Object -Property Count -Descending

Вывод выглядит так. Числа и расширения зависят от содержимого папки, порядок столбцов один и тот же.

Count Name
----- ----
   42 .log
   18 .csv
    7 .txt
    3

Строка с пустым Name — файлы без расширения.

Если убрать -NoElement, появляется столбец Group, и в нём видны сами элементы группы.

Count Name  Group
----- ----  -----
   42 .log  {app-20260601.log, app-20260602.log, app-20260603.log...}
   18 .csv  {export-01.csv, export-02.csv, export-03.csv...}

Когда нужны только числа, столбец Group забивает экран — поэтому добавляют -NoElement. Если нужно увидеть, что именно попало в группу, параметр не ставят.

Посчитаем службы по состоянию.

Get-Service |
  Group-Object -Property Status -NoElement

Посчитаем записи журнала событий по уровню.

Get-WinEvent -LogName System -MaxEvents 500 |
  Group-Object -Property LevelDisplayName -NoElement

Group-Object хорошо подходит, чтобы в начале разбора увидеть общую картину.

Каких расширений больше всего
Служб в каком состоянии больше всего
Каких уровней ошибок больше всего
В каком отделе больше всего данных

Используйте его, когда сначала хочется увидеть распределение, а не сразу лезть в детали.

9. Собрать нужные столбцы — добавить вычисляемые

Размер файла доступен через Length, но единица — байты. Смотреть сырые байты каждый раз утомительно, поэтому удобно завести столбец, пересчитанный в МБ или КБ.

Get-ChildItem . -File |
  Select-Object Name, @{Name="SizeKB"; Expression={ [math]::Round($_.Length / 1KB, 1) }}, LastWriteTime

Пример с вложенными папками: сначала самые большие файлы.

Get-ChildItem . -File -Recurse |
  Sort-Object -Property Length -Descending |
  Select-Object -First 20 FullName, @{Name="SizeMB"; Expression={ [math]::Round($_.Length / 1MB, 2) }}, LastWriteTime

@{Name="..."; Expression={ ... }} — синтаксис вычисляемого столбца. Поначалу запись кажется длинной, но на практике её используют постоянно.

Например, так можно показать использование памяти процессом в МБ.

Get-Process |
  Sort-Object -Property WorkingSet -Descending |
  Select-Object -First 10 Name, Id, @{Name="MemoryMB"; Expression={ [math]::Round($_.WorkingSet / 1MB, 1) }}

В отчёте столбец вроде SizeMB читается гораздо лучше исходного Length.

10. Смотреть от новых к старым, от старых к новым, от больших к меньшим

В PowerShell сортировка — это Sort-Object.

Недавно изменённые файлы:

Get-ChildItem . -File |
  Sort-Object -Property LastWriteTime -Descending |
  Select-Object -First 10 Name, LastWriteTime

Старые файлы:

Get-ChildItem . -File |
  Sort-Object -Property LastWriteTime |
  Select-Object -First 10 Name, LastWriteTime

Большие файлы:

Get-ChildItem . -File -Recurse |
  Sort-Object -Property Length -Descending |
  Select-Object -First 10 FullName, Length

Эти три варианта используют постоянно.

От новых к старым → LastWriteTime -Descending
От старых к новым → LastWriteTime
От больших к меньшим → Length -Descending

Это частые спутники при разборе логов, уборке лишних файлов и проверке места на диске.

11. Format-* — только в конце, для экрана

Чтобы вывод на экране читался лучше, используют Format-Table и Format-List.

Get-Process |
  Sort-Object -Property WorkingSet -Descending |
  Select-Object -First 10 Name, Id, WorkingSet |
  Format-Table -AutoSize

Для подробностей по одному объекту удобен Format-List.

Get-Process -Id $PID |
  Format-List *

Но Format-Table и Format-List — «для отображения».

Перед выводом в CSV и перед следующей командой, которая ещё будет обрабатывать данные, их лучше не ставить.

# Избегать
Get-Process |
  Format-Table Name, Id |
  Export-Csv .\process.csv -NoTypeInformation

Для CSV выбирайте столбцы через Select-Object.

# Правильно
Get-Process |
  Select-Object Name, Id |
  Export-Csv .\process.csv -NoTypeInformation -Encoding UTF8

Если сомневаетесь, рассуждайте так:

Только посмотреть на экране → Format-Table / Format-List
Результат ещё понадобится  → Select-Object

12. Поиск по логам чуть удобнее — Select-String

Для поиска строк используют Select-String.

Select-String -Path .\logs\*.log -Pattern "ERROR"

Можно указать сразу несколько шаблонов.

Select-String -Path .\logs\*.log -Pattern "ERROR", "WARN", "FATAL"

Чтобы увидеть соседние строки, используйте -Context.

Select-String -Path .\logs\*.log -Pattern "ERROR" -Context 2

Это дополнительно показывает две строки до и после найденной — удобно, когда нужно понять, что происходило вокруг ошибки.

Чтобы искать буквальную строку, используйте -SimpleMatch.

Select-String -Path .\logs\*.log -Pattern "[ERROR]" -SimpleMatch

-Pattern в Select-String по умолчанию считается регулярным выражением. Если нужно искать такие символы, как [ или ., буквально, -SimpleMatch делает намерение явным.

Поиск с учётом регистра:

Select-String -Path .\logs\*.log -Pattern "Error" -CaseSensitive

Результаты поиска тоже можно сохранить в CSV.

Select-String -Path .\logs\*.log -Pattern "ERROR" |
  Select-Object Path, LineNumber, Line |
  Export-Csv .\error-lines.csv -NoTypeInformation -Encoding UTF8

13. Замена строк

Чтобы заменить часть строки, используют -replace.

"server01.example.com" -replace "\.example\.com$", ""

Если меняете содержимое файла, безопаснее не перезаписывать исходник сразу. Сначала выведите результат в отдельный файл.

(Get-Content .\appsettings.json -Raw) -replace "localhost", "db01" |
  Set-Content .\appsettings.preview.json -Encoding UTF8

После проверки при необходимости перенесите изменения в исходный файл.

В конфигурационных файлах и массовых заменах слишком много совпадений легко приводит к ошибке. Безопаснее сначала проверить объекты через Select-String и только потом заменять.

Select-String -Path .\appsettings.json -Pattern "localhost" -SimpleMatch

14. Сравнить два результата — Compare-Object

Compare-Object показывает различия между двумя списками.

Когда это нужно: чтобы проверить, что состав не изменился до и после работы; чтобы сверить настройки или список установленного ПО на двух ПК; чтобы сравнить набор служб в продакшене и на стенде. Команда как раз для случая «должно было остаться как было».

Например, сравним списки имён файлов до и после изменений.

Compare-Object `
  -ReferenceObject (Get-Content .\before.txt) `
  -DifferenceObject (Get-Content .\after.txt)

Если в before.txt лежат a.log, b.log, c.log, а в after.txtb.log, c.log, d.log, вывод будет таким:

InputObject SideIndicator
----------- -------------
d.log       =>
a.log       <=

b.log и c.log, которые есть в обоих списках, по умолчанию не показываются. На экран попадают только различия.

Значения SideIndicator такие:

Отображение Значение
<= Есть только слева, то есть в ReferenceObject
=> Есть только справа, то есть в DifferenceObject
== Есть в обоих. Появляется, если указать -IncludeEqual

Стрелку проще запомнить так: она «тянется» к той стороне, где объект есть — к ReferenceObject (слева) или к DifferenceObject (справа). В примере выше a.log есть только слева (до изменения), значит файл исчез; d.log есть только справа (после изменения), значит файл появился.

Пример: сохранить списки имён файлов из папок и сравнить их.

Get-ChildItem .\before -File |
  Select-Object -ExpandProperty Name |
  Set-Content .\before-list.txt -Encoding UTF8

Get-ChildItem .\after -File |
  Select-Object -ExpandProperty Name |
  Set-Content .\after-list.txt -Encoding UTF8

Compare-Object `
  -ReferenceObject (Get-Content .\before-list.txt) `
  -DifferenceObject (Get-Content .\after-list.txt)

Можно посмотреть и изменения в списке служб.

Get-Service |
  Select-Object Name, Status |
  Export-Csv .\services-before.csv -NoTypeInformation -Encoding UTF8

После изменения выведите ещё раз.

Get-Service |
  Select-Object Name, Status |
  Export-Csv .\services-after.csv -NoTypeInformation -Encoding UTF8

Сравним.

Compare-Object `
  -ReferenceObject (Import-Csv .\services-before.csv) `
  -DifferenceObject (Import-Csv .\services-after.csv) `
  -Property Name, Status

Если после каждой задачи сохранять разницу «до / после», разбор и отчётность становятся проще.

15. Проверить хеш файла — Get-FileHash

Когда нужно убедиться, что скачанный или распространяемый файл совпадает с оригиналом, используют хеш.

Get-FileHash .\installer.exe -Algorithm SHA256

Пример: проверить все файлы в папке разом.

Get-ChildItem .\downloads -File |
  ForEach-Object { Get-FileHash -LiteralPath $_.FullName -Algorithm SHA256 }

Результаты можно сохранить и в CSV.

Get-ChildItem .\downloads -File |
  ForEach-Object { Get-FileHash -LiteralPath $_.FullName -Algorithm SHA256 } |
  Select-Object Path, Hash |
  Export-Csv .\hashes.csv -NoTypeInformation -Encoding UTF8

Файлы, которые по имени выглядят одинаково, по содержимому могут различаться. Для дистрибутивов, резервных копий и переносов сохранённые хеши заметно упрощают проверку.

16. Отправить в буфер обмена — Set-Clipboard

Когда это нужно: когда результат разбора нужно сразу вставить в ответ на запрос или в отчёт об инциденте, либо вставить в Excel как таблицу. Весь путь «создать файл → открыть → выделить → скопировать» просто выпадает.

Если результат команды нужно вставить в письмо или чат, удобно отправить его в буфер обмена.

Get-Service |
  Select-Object Name, Status |
  ConvertTo-Csv -NoTypeInformation |
  Set-Clipboard

Чтобы посмотреть содержимое буфера обмена:

Get-Clipboard

Чтобы вставить в Excel с разделителем-табуляцией, задайте разделитель ConvertTo-Csv как табуляцию.

Get-Process |
  Select-Object Name, Id, CPU |
  ConvertTo-Csv -NoTypeInformation -Delimiter "`t" |
  Set-Clipboard

Если результат нужен только на время, это проще, чем каждый раз создавать файл. Если нужна постоянная копия, сохраните её через Export-Csv.

17. Показать на экране и сохранить в файл — Tee-Object

Когда результат нужно видеть на экране и одновременно сохранять в файл, используют Tee-Object.

Get-Process |
  Sort-Object -Property WorkingSet -Descending |
  Select-Object -First 10 Name, Id, WorkingSet |
  Tee-Object -FilePath .\top-process.txt

Tee-Object направляет результат конвейера в двух направлениях.

Вывести на экран
Дополнительно сохранить в файл

Это подходит для сценария «смотреть и одновременно фиксировать» во время разбора. Если потом нужно открыть результат в Excel, удобнее Export-Csv.

Get-Process |
  Sort-Object -Property WorkingSet -Descending |
  Select-Object -First 10 Name, Id, WorkingSet |
  Export-Csv .\top-process.csv -NoTypeInformation -Encoding UTF8

Проще запомнить так: для экрана — Tee-Object, чтобы сохранить таблицу — Export-Csv.

18. Сохранить журнал работы — Start-Transcript

Когда это нужно: при работе в продакшене, когда потом придётся отчитаться, какие команды и в каком порядке выполнялись. Это копия для отчёта при разборе инцидента или обслуживании: команду стоит дать один раз до начала работы.

Чтобы записать последовательность действий, используют Start-Transcript.

Start-Transcript -Path .\work-log.txt

После этого записываются выполняемые команды и вывод на экран.

Завершение:

Stop-Transcript

Во время разбора позже часто хочется проверить следующее:

Какие команды выполнялись
В какой папке шла работа
Какие получились результаты
Были ли ошибки

Start-Transcript подстраховывает, если рабочие заметки вы забыть. Но если на экран в ходе работы попадают данные, которые нельзя записывать, — пароли, токены — пользуйтесь осторожно.

19. Прочитать CSV и отфильтровать по условию

В рабочих данных CSV встречается постоянно.

Например, предположим, что есть такой файл users.csv.

Name,Department,Enabled
Suzuki,Sales,true
Tanaka,Accounting,false
Sato,Sales,true

Загрузка:

Import-Csv .\users.csv

Посмотрим только людей из отдела Sales.

Import-Csv .\users.csv |
  Where-Object { $_.Department -eq "Sales" }

Выведем только активных пользователей в отдельный CSV.

Import-Csv .\users.csv |
  Where-Object { $_.Enabled -eq "true" } |
  Export-Csv .\enabled-users.csv -NoTypeInformation -Encoding UTF8

Значения из CSV чаще всего трактуются как строки, поэтому при сравнении true / false или чисел при необходимости учитывайте преобразование типов.

Например, только строки с баллом от 80:

Import-Csv .\scores.csv |
  Where-Object { [int]$_.Score -ge 80 }

20. Посмотреть значения конфигурации JSON

JSON часто встречается в конфигурационных файлах и веб-API.

$config = Get-Content .\settings.json -Raw | ConvertFrom-Json
$config

Можно посмотреть и конкретное значение.

$config.Database.Host

Пример: изменить значение и сохранить в отдельный файл.

$config.Database.Host = "db01"
$config |
  ConvertTo-Json -Depth 10 |
  Set-Content .\settings.updated.json -Encoding UTF8

При работе с JSON часто используют Get-Content -Raw. С -Raw весь файл читается как одна строка — для многострочного JSON так понятнее.

21. Посмотреть переменные окружения

Переменные окружения часто нужны для настроек приложений и проверки путей.

Список:

Get-ChildItem Env:

Текущее имя пользователя:

$env:USERNAME

Временная папка:

$env:TEMP

Разбить PATH, чтобы было удобнее читать:

$env:PATH -split ";"

Задать переменную окружения только для текущего сеанса PowerShell:

$env:APP_MODE = "Development"

Эта настройка действует только внутри текущего открытого сеанса PowerShell.

Чтобы сохранить как пользовательскую переменную окружения, сделайте так.

[Environment]::SetEnvironmentVariable("APP_MODE", "Development", "User")

Это операция, которая меняет окружение, поэтому на корпоративных ПК и в продакшене сначала проверьте область влияния.

22. Проверить профиль

В PowerShell есть профиль, который загружается при запуске.

Проверим расположение.

$PROFILE

Проверим, существует ли он.

Test-Path $PROFILE

Создание:

New-Item -ItemType File -Path $PROFILE -Force

Открыть в Блокноте:

notepad $PROFILE

В профиле удобно хранить часто используемые настройки и функции. Но если написать там слишком сложную логику, PowerShell будет дольше запускаться, а воспроизвести это в другой среде станет сложнее, поэтому сначала лучше ограничиться часто используемыми путями и настройками отображения.

23. Посмотреть процессы

При разборе процессов чаще всего сначала смотрят по убыванию использования памяти.

Get-Process |
  Sort-Object -Property WorkingSet -Descending |
  Select-Object -First 10 Name, Id, @{Name="MemoryMB"; Expression={ [math]::Round($_.WorkingSet / 1MB, 1) }}

Отфильтровать по конкретному имени:

Get-Process -Name notepad -ErrorAction SilentlyContinue

Процесс не останавливайте сразу — сначала проверьте через -WhatIf.

Stop-Process -Name notepad -WhatIf

Если всё в порядке, выполняйте.

Stop-Process -Name notepad

В продакшене остановка процесса может затронуть работу. Перед остановкой проверьте объект, кто им пользуется и как восстанавливаться.

24. Посмотреть службы

Список служб:

Get-Service

Только остановленные службы:

Get-Service |
  Where-Object { $_.Status -eq "Stopped" }

Найти службы с автоматическим запуском, которые при этом остановлены:

Get-Service |
  Where-Object { $_.StartType -eq "Automatic" -and $_.Status -ne "Running" } |
  Select-Object Name, DisplayName, Status, StartType

При перезапуске службы тоже сначала проверьте объект.

Get-Service -Name "Spooler"

Пробный прогон:

Restart-Service -Name "Spooler" -WhatIf

Операции со службами сильно влияют на систему, поэтому перед выполнением проверьте окно обслуживания и процедуру восстановления.

25. Посмотреть журнал событий

При разборе Windows часто приходится смотреть журнал событий.

Последние 100 записей журнала System:

Get-WinEvent -LogName System -MaxEvents 100 |
  Select-Object TimeCreated, ProviderName, Id, LevelDisplayName, Message

Только ошибки и предупреждения:

Get-WinEvent -LogName System -MaxEvents 500 |
  Where-Object { $_.LevelDisplayName -in @("Error", "Warning") } |
  Select-Object TimeCreated, ProviderName, Id, LevelDisplayName, Message

Только ошибки за последние 24 часа:

$start = (Get-Date).AddHours(-24)

Get-WinEvent -FilterHashtable @{ LogName = "System"; StartTime = $start } |
  Where-Object { $_.LevelDisplayName -eq "Error" } |
  Select-Object TimeCreated, ProviderName, Id, Message

Пример: сохранить результаты разбора в CSV.

Get-WinEvent -LogName System -MaxEvents 500 |
  Where-Object { $_.LevelDisplayName -in @("Error", "Warning") } |
  Select-Object TimeCreated, ProviderName, Id, LevelDisplayName, Message |
  Export-Csv .\system-events.csv -NoTypeInformation -Encoding UTF8

Журнал событий легко разрастается, поэтому диапазон важно ограничивать через -MaxEvents или указанием периода.

26. Проверить сеть

Для проверки доступности используют Test-Connection.

Test-Connection example.com -Count 4

Чтобы в Windows проверить доступность TCP-порта, удобен Test-NetConnection.

Test-NetConnection example.com -Port 443

Проверка разрешения DNS:

Resolve-DnsName example.com

При разборе сети проверку дробят так:

Разрешается ли имя
Достижим ли IP
Открыт ли нужный порт
Не мешают ли прокси или брандмауэр

Не пытайтесь судить обо всём только средствами PowerShell — удобнее использовать его как точку входа и идти по шагам.

27. Посмотреть результаты из веба

Чтобы получить веб-страницу, используют Invoke-WebRequest.

Invoke-WebRequest https://example.com |
  Select-Object StatusCode, StatusDescription

Для результатов JSON API удобен Invoke-RestMethod.

Invoke-RestMethod https://api.github.com/repos/PowerShell/PowerShell |
  Select-Object full_name, stargazers_count, forks_count

Ответ API чаще всего сразу можно обрабатывать как объекты PowerShell, и это хорошо сочетается с Select-Object и Where-Object.

При разборе внутренних API тоже начинайте с запросов на чтение (GET).

Если в запросе есть учётные данные или токены, следите за тем, что попадает на экран и в транскрипт.

28. Измерить время выполнения — Measure-Command

Когда это нужно: чтобы решить, можно ли ставить обработку в ночной пакет, или чтобы сравнить, стала ли новая запись быстрее. Решение опирается на цифры, а не на ощущение.

Когда нужно узнать, сколько времени занимает обработка, используют Measure-Command.

Measure-Command {
  Get-ChildItem C:\Windows -File -Recurse -ErrorAction SilentlyContinue |
    Measure-Object
}

В результате есть TotalSeconds и TotalMilliseconds.

$result = Measure-Command {
  Get-ChildItem . -File -Recurse | Measure-Object
}

$result.TotalSeconds

Когда скрипт нужно ускорить, важно измерять время, а не полагаться на ощущения. Но результат зависит от числа файлов, состояния диска и сети, поэтому не судите по одному запуску — проверьте несколько раз.

29. Долгие операции в фоне — Start-Job

Когда это нужно: когда полный обход большой папки или подсчёт хешей занимает минуты, и за это время хочется продолжить другой разбор. Обратное тоже верно: выносить в задание операцию на несколько секунд обычно невыгодно — дороже сам запуск.

Чтобы выполнить долгий разбор отдельным заданием, используют Start-Job.

$job = Start-Job -ScriptBlock {
  Get-ChildItem C:\Windows -File -Recurse -ErrorAction SilentlyContinue |
    Measure-Object
}

Состояние задания:

Get-Job

Получить результат:

Receive-Job $job

Удалить ненужное задание:

Remove-Job $job

Start-Job удобен, но с самого начала тащить в задания всё подряд не нужно. Сначала выполняйте как обычно и выносите в задания только медленные операции — так проще ориентироваться.

30. История команд

Когда это нужно: когда команду собирали методом проб, она наконец заработала, и её нужно перенести в инструкцию или скрипт.

Чтобы посмотреть ранее выполненные команды, используют Get-History.

Get-History

Удобнее смотреть только строки команд:

Get-History |
  Select-Object Id, CommandLine

Повторно выполнить конкретную запись истории:

Invoke-History 12

История удобна, но с её помощью можно повторно выполнить и опасные команды. Перед повторным запуском изменяющих команд вроде Remove-Item или Stop-Process из истории сначала проверьте их содержимое.

31. Посмотреть детали ошибки — Get-Error

В PowerShell 7 недавнюю ошибку подробно смотрят через Get-Error.

Get-Error

Только последнее сообщение об ошибке:

$Error[0].Exception.Message

Когда возникает ошибка, не ограничивайтесь красным текстом на экране — проверьте следующее:

На какой команде произошёл сбой
На каком пути или объекте произошёл сбой
Не проблема ли это с правами
Не отсутствует ли файл
Не проблема ли это сети или блокировки

Чтобы сохранить результаты разбора, сочетайте это с Start-Transcript и Export-Csv.

32. Часто используемые операторы сравнения

В Where-Object постоянно используют операторы сравнения.

Оператор Значение Пример
-eq Равно $_.Status -eq "Running"
-ne Не равно $_.Status -ne "Running"
-gt Больше $_.Length -gt 10MB
-ge Больше или равно $_.Length -ge 10MB
-lt Меньше $_.Length -lt 10MB
-le Меньше или равно $_.Length -le 10MB
-like Совпадение по маске $_.Name -like "*.log"
-match Совпадение по регулярному выражению $_.Name -match "^app"
-in Значение есть в списке $_.Status -in @("Running", "Paused")
-contains Список содержит значение @("a", "b") -contains "a"

Примеры.

Get-ChildItem . -File |
  Where-Object { $_.Length -gt 10MB }
Get-Service |
  Where-Object { $_.Status -in @("Running", "Paused") }
Get-ChildItem . -File |
  Where-Object { $_.Name -match "\.log$" }

Поначалу вполне достаточно -eq, -ne, -gt, -lt и -like. Когда освоитесь, -match и -in позволяют записывать условия короче.

33. Небольшие рабочие рецепты

Дальше — примеры в форме, которую можно сразу использовать в работе.

Посмотреть число файлов по расширениям

Get-ChildItem C:\Work -File -Recurse |
  Group-Object -Property Extension -NoElement |
  Sort-Object -Property Count -Descending

Так примерно понимают, что лежит в папке.

Посмотреть 20 самых больших файлов

Get-ChildItem C:\Work -File -Recurse |
  Sort-Object -Property Length -Descending |
  Select-Object -First 20 FullName, @{Name="SizeMB"; Expression={ [math]::Round($_.Length / 1MB, 2) }}

Часто нужно при разборе места на диске.

Посмотреть файлы, изменённые за последние 24 часа

$since = (Get-Date).AddHours(-24)

Get-ChildItem C:\Work -File -Recurse |
  Where-Object { $_.LastWriteTime -ge $since } |
  Select-Object FullName, Length, LastWriteTime

После инцидента так смотрят, какие файлы успели измениться.

Собрать строки логов с ERROR в CSV

Select-String -Path C:\App\Logs\*.log -Pattern "ERROR" |
  Select-Object Path, LineNumber, Line |
  Export-Csv .\error-lines.csv -NoTypeInformation -Encoding UTF8

Так результаты разбора проще передавать дальше.

Посмотреть две строки до и после ERROR

Select-String -Path C:\App\Logs\*.log -Pattern "ERROR" -Context 2

Когда нужно увидеть, что происходило вокруг причины.

Посмотреть процессы с наибольшим использованием памяти

Get-Process |
  Sort-Object -Property WorkingSet -Descending |
  Select-Object -First 10 Name, Id, @{Name="MemoryMB"; Expression={ [math]::Round($_.WorkingSet / 1MB, 1) }}

Посмотреть службы с автозапуском, которые при этом остановлены

Get-Service |
  Where-Object { $_.StartType -eq "Automatic" -and $_.Status -ne "Running" } |
  Select-Object Name, DisplayName, Status, StartType

Собрать ошибки журнала System в CSV

Get-WinEvent -LogName System -MaxEvents 500 |
  Where-Object { $_.LevelDisplayName -eq "Error" } |
  Select-Object TimeCreated, ProviderName, Id, Message |
  Export-Csv .\system-errors.csv -NoTypeInformation -Encoding UTF8

Отправить результат команды в буфер обмена

Get-Service |
  Select-Object Name, DisplayName, Status |
  ConvertTo-Csv -NoTypeInformation |
  Set-Clipboard

Удобно, когда нужно вставить в письмо или чат.

Сравнить список файлов до и после работы

Get-ChildItem C:\Work -File |
  Select-Object -ExpandProperty Name |
  Set-Content .\before.txt -Encoding UTF8

После работы снимите список ещё раз.

Get-ChildItem C:\Work -File |
  Select-Object -ExpandProperty Name |
  Set-Content .\after.txt -Encoding UTF8

Сравним.

Compare-Object (Get-Content .\before.txt) (Get-Content .\after.txt)

Посмотреть суммарный размер папки в GB

$size = Get-ChildItem C:\Work -File -Recurse |
  Measure-Object -Property Length -Sum

[math]::Round($size.Sum / 1GB, 2)

34. Оговорки при сочетании с изменяющими командами

Большая часть выше — команды чтения, и с ними можно экспериментировать сравнительно свободно. А вот эти команды — изменяющие.

Операция Команда
Копирование Copy-Item
Перемещение Move-Item
Удаление Remove-Item
Переименование Rename-Item
Остановка процесса Stop-Process
Перезапуск службы Restart-Service
Постоянная настройка переменной окружения [Environment]::SetEnvironmentVariable()

Изменяющие команды используют в таком порядке:

1. Посмотреть объекты командами Get-
2. Отфильтровать через Where-Object
3. Проверить список объектов через Select-Object
4. Посчитать через Measure-Object
5. При необходимости сохранить копию через Export-Csv
6. Если есть -WhatIf, сделать пробный прогон
7. Выполнить

Например, при удалении старых файлов .tmp.

Сначала посмотрим объекты.

$limit = (Get-Date).AddDays(-30)

$targets = Get-ChildItem C:\Temp -Filter *.tmp -File -Recurse |
  Where-Object { $_.LastWriteTime -lt $limit }

$targets |
  Select-Object FullName, Length, LastWriteTime

Посчитаем.

$targets | Measure-Object

Сохраним в CSV.

$targets |
  Select-Object FullName, Length, LastWriteTime |
  Export-Csv .\delete-targets.csv -NoTypeInformation -Encoding UTF8

Проверим, что именно будет удалено.

$targets | Remove-Item -WhatIf

Если всё в порядке, выполняйте.

$targets | Remove-Item

Один этот порядок сильно снижает число ошибок.

35. Как запоминать

Учить команды по отдельности тяжело, поэтому проще запоминать их по задаче.

Задача Команда, которую нужно вспомнить
Посчитать Measure-Object
Просуммировать Measure-Object -Sum
Посмотреть по типам Group-Object
Убрать дубликаты Sort-Object -Unique
Получить только значения Select-Object -ExpandProperty
Собрать столбцы Select-Object
Посмотреть по убыванию Sort-Object -Descending
Найти строку Select-String
Посмотреть соседний контекст Select-String -Context
Сравнить два набора Compare-Object
Сохранить копию Export-Csv / Start-Transcript
Вывести и на экран, и в файл Tee-Object
Отправить в буфер обмена Set-Clipboard
Измерить время Measure-Command
Посмотреть детали ошибки Get-Error

Шпаргалка на одну страницу

Сводная таблица с готовыми командами — её можно распечатать и держать под рукой. Большую часть повседневных задач собирают уже из неё.

Задача Готовая форма
Посчитать файлы Get-ChildItem . -File \| Measure-Object
Суммарный размер в GB [math]::Round((Get-ChildItem . -File -Recurse \| Measure-Object -Property Length -Sum).Sum / 1GB, 2)
Число файлов по расширениям Get-ChildItem . -File \| Group-Object -Property Extension -NoElement \| Sort-Object -Property Count -Descending
20 самых больших файлов Get-ChildItem . -File -Recurse \| Sort-Object Length -Descending \| Select-Object -First 20 FullName, Length
Изменённые за последние 24 часа Get-ChildItem . -File -Recurse \| Where-Object { $_.LastWriteTime -gt (Get-Date).AddDays(-1) }
Достать только значения Get-Service \| Select-Object -ExpandProperty Name
Убрать дубликаты Get-Content .\list.txt \| Sort-Object -Unique
Найти ERROR в логах Select-String -Path .\logs\*.log -Pattern "ERROR"
Две строки до и после ERROR Select-String -Path .\logs\*.log -Pattern "ERROR" -Context 2
Сравнить два списка Compare-Object -ReferenceObject (Get-Content .\before.txt) -DifferenceObject (Get-Content .\after.txt)
Проверить хеш Get-FileHash .\installer.exe -Algorithm SHA256
Результат в буфер обмена Get-Service \| Select-Object Name, Status \| ConvertTo-Csv -NoTypeInformation \| Set-Clipboard
И на экран, и в файл Get-Process \| Tee-Object -FilePath .\out.txt
Начать журнал работы Start-Transcript -Path .\work.log
Отфильтровать CSV Import-Csv .\data.csv \| Where-Object { $_.Status -eq "NG" }
Сохранить в CSV ... \| Export-Csv .\out.csv -NoTypeInformation -Encoding UTF8
Процессы с большой памятью Get-Process \| Sort-Object WorkingSet -Descending \| Select-Object -First 10 Name, Id, WorkingSet
Остановленные службы с автозапуском Get-Service \| Where-Object { $_.StartType -eq "Automatic" -and $_.Status -ne "Running" }
Ошибки журнала событий Get-WinEvent -LogName System -MaxEvents 200 \| Where-Object { $_.LevelDisplayName -eq "Error" }
Проверить доступность Test-NetConnection -ComputerName example.local -Port 443
Измерить время выполнения Measure-Command { ... }
Подробности последней ошибки Get-Error

Порядок, который нельзя пропускать

смотреть → считать → привести к виду → сохранить → пробный прогон → выполнить

Format-Table и Format-List ставят в самый конец этой цепочки — только когда смотрите на экран. Если вставить их перед Export-Csv или следующей командой, дальше конвейер ломается.

36. Итог

PowerShell по-настоящему силён, когда вы умеете писать скрипты. Но в повседневной работе чаще всего нужны как раз сочетания коротких команд.

Посчитать
Отсортировать
Сгруппировать
Сравнить
Найти
Извлечь
Сохранить
Отправить в буфер обмена
Сохранить журнал работы

Уже одно умение делать это заметно облегчает повседневную работу. Сложную автоматизацию с порога строить не нужно. Сначала научитесь точно видеть ситуацию командами чтения, а изменяющие команды вроде Copy-Item, Move-Item, Remove-Item, Restart-Service подключайте только когда это действительно нужно.

Безопасный приём работы с PowerShell — вот этот порядок:

смотреть → считать → привести к виду → сохранить → пробный прогон → выполнить

Когда этот шаблон входит в привычку, PowerShell перестаёт быть «чёрным экраном, куда вбивают команды», и становится рабочим инструментом для ежедневного разбора, наведения порядка и отчётности.

Недавние статьи с теми же тегами помогут подробнее изучить близкие темы.

Эти страницы показывают тему статьи в более широком контексте услуг и решений.

Статья напрямую связана со следующими услугами.

Частые вопросы

Вопросы, которые часто возникают при консультациях по теме статьи.

Как в PowerShell посчитать файлы и узнать суммарный размер?
Передайте результат Get-ChildItem в Measure-Object. Число файлов смотрите в свойстве Count; чтобы захватить и вложенные папки, добавьте -Recurse. Суммарный размер считают так: Measure-Object -Property Length -Sum. В байтах читать неудобно, поэтому переведите в гигабайты, например [math]::Round($size.Sum / 1GB, 2). Если добавить -Average и -Maximum, среднее и максимум получатся за тот же проход.
Чем Select-Object -ExpandProperty отличается от обычного указания свойства?
Select-Object Name возвращает таблицу объектов со столбцом Name, а Select-Object -ExpandProperty Name возвращает сами значения Name, без обёртки. Если результат уходит в CSV, лучше оставить столбец. Если значения нужно передать другой команде, в строковую обработку или в текстовый файл — удобнее -ExpandProperty. Выбор зависит от того, что вы делаете дальше.
Почему нельзя ставить Format-Table перед Export-Csv?
Format-Table и Format-List — команды для экрана: они подменяют вывод объектами форматирования, и после этого CSV и дальнейшая обработка идут уже не по исходным данным. Для CSV сначала выберите столбцы через Select-Object и только потом передайте в Export-Csv. Запомнить просто: смотрите на экран — Format-*; результат ещё понадобится — Select-Object.
Как безопасно пользоваться изменяющими командами вроде Remove-Item?
Не запускайте сразу. Сначала посмотрите объекты командами Get-, сузьте выборку через Where-Object, проверьте список через Select-Object, посчитайте через Measure-Object и при необходимости сохраните копию через Export-Csv. Если у команды есть -WhatIf, сделайте пробный прогон и убедитесь, что удалится или переместится именно то, что нужно, — и только потом выполняйте. Один этот порядок сильно снижает число ошибок.

Об авторе

Страница с профилем автора статьи.

Го Комура

Представитель KomuraSoft LLC

Специализируется на разработке программного обеспечения для Windows, техническом консалтинге и расследовании сбоев, особенно в проектах с унаследованными системами и трудно воспроизводимыми ошибками.

Публичные ссылки

Вернуться в блог