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

· · PowerShell, Windows, Командная строка, Автоматизация, Использование существующих активов

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

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

При этом с самого начала не нужно писать сложные скрипты. Если вы освоите только следующую последовательность, этого уже будет вполне достаточно для повседневной работы.

Искать  Смотреть  Фильтровать  Сортировать  Выводить  При необходимости изменять

Основа PowerShell — не «зазубривание длинных команд». Важны три вещи:

  1. Умение искать команды через Get-Command и Get-Help
  2. Умение передавать результат следующей команде через конвейер |
  3. Проверка последствий через -WhatIf и -Confirm перед удалением, остановкой или изменением

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

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

powershell-command-basics - komurasoft-blog-samples (GitHub)

2. Разница между PowerShell и командной строкой

PowerShell внешне похож на привычную командную строку (cmd.exe), но внутренняя логика отличается.

Аспект Командная строка PowerShell
Основной вывод Строки текста Объекты
Имена команд dir, copy и т. д. Get-ChildItem, Copy-Item и т. д.
Обработка результата В основном обработка строк Фильтрация и сортировка через свойства
Автоматизация Пакетные файлы Скрипты .ps1
Сильная сторона Совместимость со старыми командными активами Администрирование Windows, CSV, JSON, API, рутинные задачи

Например, при получении списка файлов в cmd.exe результат dir чаще всего просто просматривается как текст. В PowerShell файл представлен как объект со свойствами Name, Length, LastWriteTime и другими.

Get-ChildItem

Понимание этого различия позволяет естественно писать такие операции, как «показать только файлы, изменённые за последние 7 дней, в порядке от новых к старым».

Get-ChildItem -File |
  Where-Object { $_.LastWriteTime -gt (Get-Date).AddDays(-7) } |
  Sort-Object LastWriteTime -Descending |
  Select-Object Name, Length, LastWriteTime

3. Windows PowerShell 5.1 и PowerShell 7.x

В Windows издавна присутствует Windows PowerShell 5.1, а также новая линейка PowerShell 7.x.

На практике удобно рассуждать так.

Вид Исполняемый файл Основное назначение
Windows PowerShell 5.1 powershell.exe Старые модули, специфичные для Windows, существующие скрипты, сопровождение внутренних активов
PowerShell 7.x pwsh.exe Новые скрипты, кроссплатформенность, постоянные улучшения функциональности

Для нового изучения вполне можно ориентироваться на PowerShell 7.x. Однако старые внутренние управляющие скрипты и модули, специфичные для Windows, иногда рассчитаны именно на Windows PowerShell 5.1.

Поэтому на практике сначала проверяют версию.

$PSVersionTable

Для скриптов, которые должны запускаться только на определённой версии и выше, в начале файла стоит указать условие — это снижает число аварий.

#Requires -Version 7.0

4. Имена командлетов в форме «глагол-существительное»

Стандартные команды PowerShell в основном имеют форму Глагол-Существительное.

Get-Process
Get-Service
Get-ChildItem
Copy-Item
Remove-Item
Export-Csv

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

Глагол Значение Пример
Get получить Get-Process
Set задать Set-Location
New создать New-Item
Copy скопировать Copy-Item
Move переместить Move-Item
Remove удалить Remove-Item
Start запустить Start-Service
Stop остановить Stop-Process
Import загрузить Import-Csv
Export выгрузить Export-Csv

Короткие имена вроде dir, ls, cat, cd тоже можно использовать, но большинство из них — псевдонимы (aliases).

Get-Command dir

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

# читается легко, но в скриптах лучше избегать
ls *.log

# намерение понятно однозначно
Get-ChildItem -Filter *.log

5. Три команды для исследования, которые стоит выучить первыми

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

1. Get-Command — найти доступные команды

Get-Command — команда для поиска установленных команд, функций, псевдонимов и приложений.

# Найти команды с существительным Process
Get-Command -Noun Process

# Найти команды, связанные со службами
Get-Command *Service*

# Найти команды, связанные с CSV
Get-Command *Csv*

Когда имя команды помнится не точно, используйте символы подстановки.

Get-Command *Item*
Get-Command *Content*
Get-Command *Json*

2. Get-Help — посмотреть, как использовать команду

Get-Help — команда для просмотра описания команды, параметров и примеров.

Get-Help Get-ChildItem
Get-Help Get-ChildItem -Examples
Get-Help Get-ChildItem -Full
Get-Help Get-ChildItem -Online

Сначала удобнее всего -Examples.

Get-Help Where-Object -Examples

Если справка устарела или её не хватает, обновите её из PowerShell, запущенного с правами администратора.

Update-Help

В зависимости от окружения для этого нужен доступ в интернет и права. На корпоративных ПК это может не сработать из-за прокси или политик управления.

3. Get-Member — посмотреть содержимое объекта

Вывод PowerShell в большинстве случаев — это не «строка текста», а «объект». С помощью Get-Member можно посмотреть, какие свойства и методы есть у этого объекта.

Get-Process | Get-Member
Get-Service | Get-Member
Get-ChildItem | Get-Member

Например, у службы есть свойства Status, Name и другие.

Get-Service | Select-Object Name, Status

У файла есть Name, Length, LastWriteTime и другие.

Get-ChildItem -File | Select-Object Name, Length, LastWriteTime

Когда непонятно, «по чему фильтровать», сначала проверьте имена свойств через Get-Member.

6. Основы конвейера

| в PowerShell передаёт результат левой команды правой команде.

Get-Process | Sort-Object CPU -Descending | Select-Object -First 10

В этом примере обработка идёт слева направо в таком порядке.

Получить список процессов
   отсортировать по убыванию использования CPU
   показать только первые 10

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

Команда Роль Пример
Where-Object Фильтрация по условию Получить только остановленные службы
Sort-Object Сортировка Отсортировать по времени изменения, от новых к старым
Select-Object Выбор столбцов или количества Показать только имя и размер
ForEach-Object Обработка каждого элемента Обработать каждый файл по отдельности
Export-Csv Вывод в CSV Сохранить результаты исследования

Where-Object — фильтрация по условию

# Показать только остановленные службы
Get-Service | Where-Object { $_.Status -eq "Stopped" }

# Показать только файлы размером более 100 МБ
Get-ChildItem -File |
  Where-Object { $_.Length -gt 100MB }

# Показать только файлы, в имени которых есть backup
Get-ChildItem -File |
  Where-Object { $_.Name -like "*backup*" }

$_ представляет текущий объект, проходящий через конвейер.

Where-Object { $_.Length -gt 100MB }

Это означает проверку: «больше ли Length рассматриваемого сейчас файла, чем 100 МБ».

Начиная с PowerShell 3.0 доступен и упрощённый синтаксис.

Get-Service | Where-Object Status -EQ "Stopped"

Однако пока вы новичок, синтаксис со scriptblock проще для понимания смысла.

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

Sort-Object — сортировка

# По убыванию использования памяти
Get-Process |
  Sort-Object WorkingSet -Descending |
  Select-Object -First 10 Name, Id, WorkingSet

# По убыванию времени изменения (сначала новые)
Get-ChildItem -File |
  Sort-Object LastWriteTime -Descending |
  Select-Object -First 20 Name, LastWriteTime

Select-Object — выбрать только нужные столбцы

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

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

Get-Process | Select-Object -First 5
Get-Process | Select-Object -Last 5

Перед выводом в CSV удобно заранее оставить только нужные столбцы через Select-Object.

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

7. Команды Format-* используйте в самом конце

В PowerShell есть команды для форматирования вывода.

Format-Table
Format-List
Format-Wide

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

# Избегать: в CSV попадает информация для отображения
Get-Process |
  Format-Table Name, CPU |
  Export-Csv .\process.csv -NoTypeInformation

# Правильно: сначала выбрать свойства, затем вывести в CSV
Get-Process |
  Select-Object Name, CPU |
  Export-Csv .\process.csv -NoTypeInformation -Encoding UTF8

Если запомнить Format-* как «команды для показа на экране в самом конце», аварий станет меньше.

8. Основы работы с файлами и папками

Чаще всего в PowerShell используются операции с файлами и папками.

Что нужно сделать Команда
Посмотреть текущее расположение Get-Location
Перейти в другое расположение Set-Location
Посмотреть список Get-ChildItem
Создать файл или папку New-Item
Скопировать Copy-Item
Переместить Move-Item
Переименовать Rename-Item
Удалить Remove-Item
Проверить существование Test-Path

Проверить текущее расположение

Get-Location

Переход.

Set-Location C:\Work

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

Set-Location "C:\Work Files\Reports"

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

Get-ChildItem
Get-ChildItem -File
Get-ChildItem -Directory
Get-ChildItem -Recurse

Для фильтрации по расширению удобен -Filter.

Get-ChildItem -Filter *.log

Для поиска с учётом подпапок используйте -Recurse.

Get-ChildItem C:\Logs -Filter *.log -Recurse

В местах с большим количеством файлов не запускайте -Recurse сразу — сначала ограничьте целевую папку.

Создание

# Создание папки
New-Item -ItemType Directory -Path .\archive

# Создание пустого файла
New-Item -ItemType File -Path .\memo.txt

Если объект может уже существовать, сначала проверьте это.

if (-not (Test-Path .\archive)) {
  New-Item -ItemType Directory -Path .\archive
}

Копирование

Copy-Item .\report.xlsx .\backup\report.xlsx

Для копирования всей папки используйте -Recurse.

Copy-Item .\data .\backup\data -Recurse

Если возможна перезапись, заранее проверьте последствия.

Copy-Item .\data .\backup\data -Recurse -WhatIf

Перемещение

Move-Item .\old.log .\archive\old.log

При перемещении нескольких файлов по условию сначала добавьте -WhatIf.

Get-ChildItem .\logs -Filter *.log |
  Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-30) } |
  Move-Item -Destination .\archive -WhatIf

Если всё в порядке, уберите -WhatIf.

Get-ChildItem .\logs -Filter *.log |
  Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-30) } |
  Move-Item -Destination .\archive

Удаление

Удаление требует особой осторожности.

Remove-Item .\old.log -WhatIf

Выполняйте только после проверки правильности объекта.

Remove-Item .\old.log

Сочетание символов подстановки и -Recurse — мощный инструмент. Не запускайте его сразу в рабочей папке — сначала проверьте через вывод списка.

# Сначала проверить объекты
Get-ChildItem C:\Logs -Filter *.tmp -Recurse |
  Select-Object FullName, Length, LastWriteTime

# Затем проверить план удаления
Get-ChildItem C:\Logs -Filter *.tmp -Recurse |
  Remove-Item -WhatIf

# И наконец выполнить
Get-ChildItem C:\Logs -Filter *.tmp -Recurse |
  Remove-Item

9. Чтение, поиск и запись текстовых файлов

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

Чтение файла

Get-Content .\app.log

Чтобы посмотреть только конец файла, используйте -Tail.

Get-Content .\app.log -Tail 50

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

Get-Content .\app.log -Tail 20 -Wait

Поиск строк

Select-String -Path .\app.log -Pattern "ERROR"

Можно указать несколько файлов.

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

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

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

Запись в файл

"hello" | Set-Content .\memo.txt -Encoding UTF8
"next line" | Add-Content .\memo.txt -Encoding UTF8

Для сохранения результата команды Export-Csv или ConvertTo-Json иногда удобнее для дальнейшей работы, чем Out-File.

Get-Process |
  Select-Object Name, Id, CPU |
  Export-Csv .\process.csv -NoTypeInformation -Encoding UTF8

10. Основы работы с CSV

В автоматизации бизнес-процессов CSV встречается очень часто. В PowerShell CSV обрабатывается не как строки текста, а как «объекты со столбцами».

Чтение CSV

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

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

Загрузка.

$users = Import-Csv .\users.csv
$users

Имена столбцов становятся свойствами.

$users | Select-Object Name, Department

Фильтрация по условию

$users |
  Where-Object { $_.Department -eq "Sales" }

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

$users |
  Where-Object { $_.Enabled -eq "true" }

Вывод в CSV

$users |
  Where-Object { $_.Department -eq "Sales" } |
  Export-Csv .\sales-users.csv -NoTypeInformation -Encoding UTF8

Железное правило — никогда не ставить Format-Table перед Export-Csv.

# Избегать
$users | Format-Table | Export-Csv .\out.csv -NoTypeInformation

# Правильно
$users | Select-Object Name, Department, Enabled | Export-Csv .\out.csv -NoTypeInformation -Encoding UTF8

11. Основы работы с JSON

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

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

Преобразование объекта в JSON.

[pscustomobject]@{
  Name = "BatchJob"
  Enabled = $true
  Retry = 3
} | ConvertTo-Json

При наличии глубокой вложенности укажите -Depth.

$config | ConvertTo-Json -Depth 10 | Set-Content .\settings.json -Encoding UTF8

12. Основы работы с процессами и службами

Просмотр процессов

Get-Process

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

Get-Process |
  Sort-Object WorkingSet -Descending |
  Select-Object -First 10 Name, Id, WorkingSet

Фильтрация по имени.

Get-Process -Name notepad

Остановку выполняйте осторожно.

Stop-Process -Name notepad -WhatIf

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

Stop-Process -Name notepad

Просмотр служб

Get-Service

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

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

Фильтрация по имени.

Get-Service -Name "Spooler"

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

Get-Service -Name "Spooler"
Restart-Service -Name "Spooler" -WhatIf

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

13. Основы работы с журналом событий

При исследовании Windows журнал событий незаменим.

Проверка недавних ошибок.

Get-WinEvent -LogName System -MaxEvents 100 |
  Where-Object { $_.LevelDisplayName -eq "Error" } |
  Select-Object TimeCreated, ProviderName, Id, Message

Просмотр последних 50 записей журнала приложений.

Get-WinEvent -LogName Application -MaxEvents 50 |
  Select-Object TimeCreated, ProviderName, Id, LevelDisplayName, Message

Фильтрация по периоду.

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

Get-WinEvent -FilterHashtable @{
  LogName = "System"
  StartTime = $start
} |
  Select-Object TimeCreated, ProviderName, Id, LevelDisplayName, 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

14. Переменные, массивы и хеш-таблицы

Работать можно и короткими командами, но когда код становится длиннее, удобны переменные.

Переменные

$path = "C:\Logs"
Get-ChildItem $path

Переменные PowerShell начинаются с $.

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

Массивы

$extensions = @("*.log", "*.txt", "*.csv")
foreach ($ext in $extensions) {
  Get-ChildItem C:\Work -Filter $ext
}

Хеш-таблицы

Хеш-таблица — это набор пар «ключ-значение».

$params = @{
  Path = "C:\Logs"
  Filter = "*.log"
  Recurse = $true
}

Get-ChildItem @params

Такая запись через @params называется «сплаттингом» (splatting). Она делает код читаемее при увеличении числа параметров.

15. Оформление результатов через PSCustomObject

Когда нужно собрать результаты исследования в табличном виде, удобен [pscustomobject].

[pscustomobject]@{
  ComputerName = $env:COMPUTERNAME
  UserName     = $env:USERNAME
  CheckedAt    = Get-Date
}

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

Get-ChildItem C:\Logs -Filter *.log |
  ForEach-Object {
    [pscustomobject]@{
      Name          = $_.Name
      FullName      = $_.FullName
      SizeMB        = [math]::Round($_.Length / 1MB, 2)
      LastWriteTime = $_.LastWriteTime
    }
  } |
  Export-Csv .\log-files.csv -NoTypeInformation -Encoding UTF8

16. Основы файлов скриптов .ps1

Часто используемую обработку оформляйте в виде файлов .ps1.

В качестве примера создадим скрипт, выводящий список старых логов.

# Find-OldLogs.ps1
param(
  [string]$Path = "C:\Logs",
  [int]$Days = 30,
  [string]$OutputPath = ".\old-logs.csv"
)

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

Get-ChildItem -Path $Path -Filter *.log -File -Recurse |
  Where-Object { $_.LastWriteTime -lt $limit } |
  Select-Object FullName, Length, LastWriteTime |
  Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8

Write-Host "Exported: $OutputPath"

Пример запуска.

.\Find-OldLogs.ps1 -Path C:\Logs -Days 60 -OutputPath .\old-logs.csv

Если принимать аргументы через param(), условия становится проще менять впоследствии.

17. Основы политики выполнения

При попытке запустить .ps1 может появиться такая ошибка.

Выполнение сценариев отключено в данной системе...

В этом случае проверьте текущую политику выполнения.

Get-ExecutionPolicy
Get-ExecutionPolicy -List

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

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

Однако на корпоративных ПК это может контролироваться групповой политикой. Не пытайтесь обойти это принудительно — уточните у администратора и внутренних правил.

Политика выполнения — это функция безопасности, контролирующая условия запуска скриптов в PowerShell. Однако это не полноценная граница безопасности. В организации её нужно рассматривать вместе с подписью, AppLocker, Microsoft Defender, управлением правами и аудитом логов.

18. Основы обработки ошибок

PowerShell иногда продолжает выполнение даже при возникновении ошибок.

Для важных операций используйте -ErrorAction Stop и try/catch.

try {
  Copy-Item .\source.txt .\backup\source.txt -ErrorAction Stop
  Write-Host "Copy succeeded"
}
catch {
  Write-Error "Copy failed: $($_.Exception.Message)"
}

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

$results = foreach ($file in Get-ChildItem .\input -File) {
  try {
    Copy-Item $file.FullName .\backup -ErrorAction Stop

    [pscustomobject]@{
      FileName = $file.Name
      Status   = "OK"
      Message  = ""
    }
  }
  catch {
    [pscustomobject]@{
      FileName = $file.Name
      Status   = "NG"
      Message  = $_.Exception.Message
    }
  }
}

$results | Export-Csv .\copy-result.csv -NoTypeInformation -Encoding UTF8

19. Безопасный порядок выполнения изменяющих команд

В PowerShell важна процедура безопасной работы с изменяющими командами — удаление, перемещение, остановка.

Базовый порядок такой:

1. Посмотреть объекты через команды Get-
2. Отфильтровать через Where-Object
3. Проверить список объектов через Select-Object
4. Зафиксировать через Export-Csv
5. Проверить план изменений через -WhatIf
6. Выполнить по-настоящему

Рассмотрим пример удаления файлов .tmp старше 30 дней.

Шаг 1. Посмотреть объекты

Get-ChildItem C:\Temp -Filter *.tmp -File -Recurse

Шаг 2. Отфильтровать по условию

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

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

Шаг 3. Показать только нужные столбцы

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

$targets |
  Select-Object FullName, Length, LastWriteTime

Шаг 4. Зафиксировать след

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

Шаг 5. Проверить через WhatIf

$targets | Remove-Item -WhatIf

Шаг 6. Выполнить

$targets | Remove-Item

Соблюдение этого порядка снижает риск аварий вроде «непонятно, что было удалено».

20. Список часто используемых базовых команд

Расположение и файлы

Цель Пример команды
Показать текущую папку Get-Location
Перейти в папку Set-Location C:\Work
Показать список Get-ChildItem
Показать только файлы Get-ChildItem -File
Показать только папки Get-ChildItem -Directory
Искать и в подпапках Get-ChildItem -Recurse
Проверить существование Test-Path .\file.txt
Создать папку New-Item -ItemType Directory .\backup
Скопировать Copy-Item .\a.txt .\backup\a.txt
Переместить Move-Item .\a.txt .\archive\a.txt
Проверить план удаления Remove-Item .\a.txt -WhatIf

Обработка объектов

Цель Пример команды
Отфильтровать по условию Where-Object { $_.Status -eq "Running" }
Отсортировать Sort-Object LastWriteTime -Descending
Выбрать столбцы Select-Object Name, LastWriteTime
Показать только верхние записи Select-Object -First 10
Обработать каждый элемент ForEach-Object { $_.Name }
Проверить содержимое Get-Member

Ввод и вывод

Цель Пример команды
Прочитать текст Get-Content .\app.log
Посмотреть конец файла Get-Content .\app.log -Tail 50
Поиск строк Select-String -Path .\app.log -Pattern "ERROR"
Прочитать CSV Import-Csv .\users.csv
Вывести CSV Export-Csv .\out.csv -NoTypeInformation -Encoding UTF8
Прочитать JSON Get-Content .\a.json -Raw | ConvertFrom-Json
Вывести JSON $obj | ConvertTo-Json -Depth 10

Исследование Windows

Цель Пример команды
Список процессов Get-Process
Список служб Get-Service
Журнал событий Get-WinEvent -LogName System -MaxEvents 100
Переменные окружения Get-ChildItem Env:
Версия PowerShell $PSVersionTable
Политика выполнения Get-ExecutionPolicy -List

21. Практический пример: исследовать логи и составить отчёт

Рассмотрим такое требование.

Из файлов .log в C:\App\Logs, изменённых за последние 7 дней, найти строки, содержащие ERROR, и собрать их в CSV.

Не будем сразу писать готовый вариант, а построим его поэтапно.

Шаг 1. Найти файлы логов

Get-ChildItem C:\App\Logs -Filter *.log -File -Recurse

Шаг 2. Отфильтровать за последние 7 дней

$since = (Get-Date).AddDays(-7)

Get-ChildItem C:\App\Logs -Filter *.log -File -Recurse |
  Where-Object { $_.LastWriteTime -ge $since }

Шаг 3. Искать ERROR

$since = (Get-Date).AddDays(-7)

Get-ChildItem C:\App\Logs -Filter *.log -File -Recurse |
  Where-Object { $_.LastWriteTime -ge $since } |
  Select-String -Pattern "ERROR"

Шаг 4. Вывести в CSV

$since = (Get-Date).AddDays(-7)

Get-ChildItem C:\App\Logs -Filter *.log -File -Recurse |
  Where-Object { $_.LastWriteTime -ge $since } |
  Select-String -Pattern "ERROR" |
  Select-Object Path, LineNumber, Line |
  Export-Csv .\error-report.csv -NoTypeInformation -Encoding UTF8

Шаг 5. Оформить в виде скрипта

# Export-ErrorReport.ps1
param(
  [string]$LogPath = "C:\App\Logs",
  [int]$Days = 7,
  [string]$Pattern = "ERROR",
  [string]$OutputPath = ".\error-report.csv"
)

$since = (Get-Date).AddDays(-$Days)

Get-ChildItem $LogPath -Filter *.log -File -Recurse |
  Where-Object { $_.LastWriteTime -ge $since } |
  Select-String -Pattern $Pattern |
  Select-Object Path, LineNumber, Line |
  Export-Csv $OutputPath -NoTypeInformation -Encoding UTF8

Write-Host "Exported: $OutputPath"

Пример запуска.

.\Export-ErrorReport.ps1 -LogPath C:\App\Logs -Days 14 -Pattern "ERROR|FATAL" -OutputPath .\errors.csv

22. Практический пример: архивирование старых файлов

Следующий пример — не удаление, а перемещение.

Из C:\Work\Reports переместить файлы .xlsx, не изменявшиеся 90 дней и более, в C:\Work\Archive.

Проверка объектов

$source = "C:\Work\Reports"
$dest = "C:\Work\Archive"
$limit = (Get-Date).AddDays(-90)

$targets = Get-ChildItem $source -Filter *.xlsx -File |
  Where-Object { $_.LastWriteTime -lt $limit }

$targets | Select-Object FullName, Length, LastWriteTime

Создание папки для архива

if (-not (Test-Path $dest)) {
  New-Item -ItemType Directory -Path $dest
}

Вывод следа

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

Проверка через WhatIf

$targets | Move-Item -Destination $dest -WhatIf

Выполнение

$targets | Move-Item -Destination $dest

Если возможны совпадения имён файлов, в таком виде операция завершится ошибкой. На практике заранее определяют правила: разделять по папкам год-месяц, добавлять дату и время к имени файла назначения, пропускать, если файл с таким именем уже существует.

23. Частые затруднения

Симптом Причина Решение
Команды слишком длинные, не запомнить Попытка зазубрить Искать через Get-Command, Get-Help -Examples
Непонятно, что такое $_ Недостаточное понимание текущего значения конвейера Запомнить в форме Where-Object { $_.Name -like "*log*" }
Странное содержимое CSV Export-Csv вызывается после Format-Table Вызывать Export-Csv после Select-Object
Ошибка при пробелах в пути Отсутствуют кавычки Заключить в кавычки: "C:\Work Files\a.txt"
Скрипт не запускается Политика выполнения Проверить через Get-ExecutionPolicy -List
Слишком много объектов для удаления Условие слишком широкое Сначала проверить через Select-Object FullName и -WhatIf
Непонятны имена свойств Не просмотрена структура объекта Использовать Get-Member
Искажение символов Несовпадение предположений о кодировке Проверить -Encoding при вводе/выводе и используемое приложение

24. Порядок изучения команд

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

Рекомендуем такой порядок.

Этап 1. Смотреть и искать

Get-Command
Get-Help
Get-Member
Get-Location
Set-Location
Get-ChildItem
Get-Content
Select-String

Этап 2. Фильтровать и оформлять

Where-Object
Sort-Object
Select-Object
ForEach-Object
Format-Table
Format-List

Этап 3. Ввод и вывод

Import-Csv
Export-Csv
ConvertFrom-Json
ConvertTo-Json
Set-Content
Add-Content
Out-File

Этап 4. Изменение

New-Item
Copy-Item
Move-Item
Rename-Item
Remove-Item
Start-Service
Stop-Service
Restart-Service
Stop-Process

Изменяющие команды всегда изучайте в паре с проверочными.

# Смотреть
Get-ChildItem .\logs -Filter *.tmp

# Смотреть план удаления
Get-ChildItem .\logs -Filter *.tmp | Remove-Item -WhatIf

# Выполнить
Get-ChildItem .\logs -Filter *.tmp | Remove-Item

25. Практический эксплуатационный чек-лист

При использовании PowerShell в рабочих задачах безопаснее проверить следующие пункты.

  • проверено, какой PowerShell запускается — powershell.exe или pwsh.exe;
  • версия проверена через $PSVersionTable;
  • перед изменением объекты выведены через команды Get-*;
  • условия Where-Object проверены на экране;
  • перед удалением, перемещением или остановкой использован -WhatIf;
  • список объектов перед выполнением сохранён в CSV;
  • в рабочей среде заранее проверены резервное копирование или процедура восстановления;
  • проверены политика выполнения скрипта и внутренние правила;
  • подготовлен вывод логов на случай ошибки;
  • в общих скриптах использованы полные имена команд, а не псевдонимы.

26. Итог

Основа PowerShell — не запоминание огромного числа команд. На практике окупается освоение такой схемы:

Искать через Get-Command
Смотреть способ использования через Get-Help
Проверять свойства через Get-Member
Смотреть объекты через Get-*
Фильтровать через Where-Object
Оформлять столбцы через Select-Object
Фиксировать след через Export-Csv
Проверять план изменений через -WhatIf
Выполнять в последнюю очередь

PowerShell — это мощная среда, способная удалять файлы, останавливать службы, завершать процессы и даже работать с реестром. Именно поэтому первым делом стоит выучить не «опасные команды», а «процедуру безопасной проверки объектов».

Смотреть  Фильтровать  Фиксировать  Прогонять  Выполнять

Если соблюдать этот порядок, PowerShell перестаёт быть просто «чёрным экраном» и становится практичным инструментом для упорядочивания, исследования и автоматизации задач Windows.

Справочные ссылки

Похожие статьи

Услуги, связанные с этой темой

Разработка Windows-приложений

Мы поддерживаем разработку Windows-ПО: бизнес-приложения, интеграцию с оборудованием, коммуникационные инструменты.

Посмотреть услугу / Связаться с нами

Использование и миграция существующих активов

Мы поддерживаем инвентаризацию, доработку и миграцию существующих активов, включая старые batch-файлы, VBScript, VBA, PowerShell, COM / ActiveX.

Связаться с нами

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

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

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

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

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

С чего начать изучение PowerShell?
Не с запоминания команд, а с того, как их искать. Важны три вещи: умение находить команды через Get-Command и Get-Help, умение передавать результат следующей команде через конвейер (|), и привычка проверять последствия через -WhatIf или -Confirm перед удалением, остановкой или изменением. Если непонятно имя свойства объекта, содержимое можно посмотреть через Get-Member. Базовый порядок действий: «искать → смотреть → фильтровать → сортировать → выводить → при необходимости изменять».
В чём разница между PowerShell и командной строкой?
Главное отличие в том, что вывод командной строки — это в основном строки текста, а вывод PowerShell — объекты. Например, файл представлен как объект со свойствами Name, Length, LastWriteTime и другими, поэтому фильтрация через Where-Object и сортировка через Sort-Object пишутся естественно. Имена команд тоже унифицированы в форме «глагол-существительное», например Get-ChildItem или Copy-Item, что упрощает поиск незнакомых команд.
Что использовать — Windows PowerShell 5.1 или PowerShell 7.x?
Для нового изучения вполне можно ориентироваться на PowerShell 7.x (pwsh.exe). Однако старые внутренние управляющие скрипты и модули, специфичные для Windows, иногда рассчитаны именно на Windows PowerShell 5.1 (powershell.exe). На практике стоит сначала проверить версию через $PSVersionTable, а для скриптов, которым нужна определённая минимальная версия, в начале файла стоит указать условие вроде #Requires -Version 7.0 — это снижает число аварий.
Как безопасно выполнять удаление и изменения в PowerShell?
Соблюдать порядок «смотреть → фильтровать → фиксировать → прогонять → выполнять». Конкретно: сначала вывести объекты командами Get-, отфильтровать через Where-Object, проверить список через Select-Object, зафиксировать след в CSV через Export-Csv, проверить план изменений через -WhatIf и только после этого выполнить операцию по-настоящему. PowerShell позволяет выполнять исследование и изменение на одном и том же экране, поэтому важна привычка начинать с проверок, доступных только для чтения.

Об авторе

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

Го Комура

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

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

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

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