Философия PowerShell. Часть 3: Навигация и управление файловой системой. Знакомство с операторами логики и функциями
Дисклеймер. в редакторе пикабу нет редактора кода поэтому картинки и вырвиглазное форматирование. Но на гитхабе лежит полноценная статья. Вы можете почитать тут, а примеры копировать из гитхаб
В предыдущей части мы исследовали конвейеры и абстрактные объекты процессов. Теперь давайте применим наши знания о конвейере и объектах к одной из частых задач пользователя или администратора — работе с файловой системой. В PowerShell эта работа построена на тех же принципах: команды возвращают объекты, которые можно передавать по конвейеру для дальнейшей обработки.
1. Концепция PowerShell Drives (PSDrives)
Прежде чем начать работать с файлами, важно понять концепцию PowerShell-дисков (PSDrives). В отличие от cmd.exe, где диски — это только буквы C:, D: и так далее, в PowerShell "диск" — это абстракция для доступа к любому иерархическому хранилищу данных.
> Get-PSDrive
Результат покажет не только физические диски, но и псевдо-диски:
Эта унификация означает, что вы можете "зайти" в реестр (Set-Location HKLM:) и получить список его ключей той же командой Get-ChildItem, которой получаете список файлов на диске C:. Это невероятно мощная концепция.
Примеры работы с различными провайдерами
Хранилище сертификатов (Cert:) Позволяет работать с цифровыми сертификатами так, будто это файлы в папках.
Задача: Найти все SSL-сертификаты на локальной машине, срок действия которых истекает в ближайшие 30 дней.
> Set-Location Cert:\LocalMachine\My
> Get-ChildItem | Where-Object { $_.NotAfter -lt (Get-Date).AddDays(30) } | Select-Object Subject, NotAfter, Thumbprint
Переменные окружения (Env:) Предоставляет доступ к переменным окружения Windows (%PATH%, %windir% и т.д.) как к файлам.
Задача: Получить путь к системной папке Windows и добавить к нему путь к System32.
Получаем значение переменной windir:
> $windowsPath = (Get-Item Env:windir).Value
Собираем полный путь
> $system32Path = Join-Path -Path $windowsPath -ChildPath "System32"
> Write-Host $system32Path
Реестр Windows (HKCU: и HKLM:) Представьте, что реестр — это просто еще одна файловая система. Ветки — это папки, а параметры — свойства этих папок.
Задача: Узнать полное название установленной версии Windows из реестра.
Переходим в нужную ветку реестра:
> Set-Location "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion"
Получаем свойство (параметр реестра) с именем "ProductName"
> Get-ItemProperty -Path . -Name "ProductName"
Переменные сессии (Variable:) Позволяет управлять всеми переменными ($myVar, $PROFILE, $Error и т.д.), определенными в текущей сессии.
Задача: Найти все переменные, связанные с версией PowerShell ($PSVersionTable, $PSHOME и др.).
Находим все переменные, начинающиеся с "PS":
> Get-ChildItem Variable:PS*
Получаем значение конкретной переменной:
> Get-Variable -Name "PSVersionTable"
2. Навигация и анализ
Основы навигации
- Узнать, где мы находимся (возвращает объект PathInfo):
> Get-Location # Псевдонимы: gl, pwd
- Переход в корень диска C:
> Set-Location C:\ # Псевдонимы: sl, cd
- Переход в домашнюю папку текущего пользователя:
> Set-Location ~
Показать содержимое текущей папки (возвращает коллекцию объектов):
> Get-ChildItem # Псевдонимы: gci, ls, dir
- Рекурсивный поиск. Найти файл hosts в системе, игнорируя ошибки "Доступ запрещен":
> Get-ChildItem C:\ -Filter "hosts" -Recurse -ErrorAction SilentlyContinue
Ключ -Recurse (Рекурсивно): Заставляет командлет работать не только с указанным элементом, но и со всем его содержимым.
Ключ -ErrorAction SilentlyContinue: Инструкция игнорировать ошибки и продолжать работу молча.
Анализ дискового пространства
Классический пример мощи конвейера: найти, отсортировать, отформатировать и выбрать.
Подсказка как вводить длинные команды.
PowerShell позволяет разбивать их на несколько строк для удобства чтения.
После оператора конвейера (|): Это самый частый и удобный способ. Просто нажмите Enter после символа |. PowerShell увидит, что команда не завершена, и будет ждать продолжения на следующей строке.
В любом другом месте: Используйте символ обратной кавычки (backtick) ` в конце строки, а затем нажмите Enter. Этот символ говорит PowerShell: "Команда продолжится на следующей строке".
В редакторах (ISE, VS Code): Сочетание клавиш Shift+Enter обычно автоматически вставляет перенос строки, не запуская команду.
Фильтрация содержимого и операторы логики
- Найти все .exe файлы. Параметр -Filter работает очень быстро:
> Get-ChildItem C:\Windows -Filter "*.exe"
Get-ChildItem возвращает коллекцию объектов. Мы можем передать ее по конвейеру в Where-Object для дальнейшей фильтрации.
> Get-ChildItem C:\Windows | Where-Object { $_.PSIsContainer -eq $false }
Эта команда знакомит нас с одним из фундаментальных понятий в скриптах PowerShell: операторами сравнения.
Операторы сравнения и логики
Это специальные ключи для сравнения значений. Они всегда начинаются с дефиса (-) и являются основой для фильтрации данных в Where-Object и построения логики в if.
Тема операторов логики - очень обширная и я ей посвящу отдельную часть (или даже две). А пока вооружившись этими операторами, мы можем фильтровать, сортировать и выбирать нужные нам файлы и папки, используя всю мощь объектного конвейера.
Примеры использования в файловой системе
Найти файл по точному имени (с учетом регистра):
> Get-ChildItem C:\Windows\System32 -Recurse | Where-Object { $_.Name -eq "kernel32.dll" }
Найти все файлы, начинающиеся с "host", но не являющиеся папками:
> Get-ChildItem C:\Windows\System32\drivers\etc | Where-Object { ($_.Name -like "host*") -and (-not $_.PSIsContainer) }
Найти все файлы журналов (.log), размер которых превышает 50 мегабайт:
> Get-ChildItem C:\Windows\Logs -Filter "*.log" -Recurse | Where-Object { $_.Length -gt 50MB }
Найти все временные файлы (.tmp) и файлы бэкапов (.bak) для очистки: Оператор -in здесь гораздо элегантнее, чем несколько условий с -or.
> $extensionsToDelete = ".tmp", ".bak", ".old" Get-ChildItem C:\Temp -Recurse | Where-Object { > $_.Extension -in $extensionsToDelete }
Найти все файлы Word (.docx), созданные за последнюю неделю:
> $oneWeekAgo = (Get-Date).AddDays(-7) Get-ChildItem C:\Users\MyUser\Documents -Filter "*.docx" -Recurse | Where-Object { $_.CreationTime -ge $oneWeekAgo }
Найти пустые файлы (размером 0 байт), которые не являются папками:
> Get-ChildItem C:\Downloads -Recurse | Where-Object { ($_.Length -eq 0) -and (-not $_.PSIsContainer) }
Найти все исполняемые файлы (.exe), которые были изменены в этом году, но НЕ в этом месяце. Этот сложный пример демонстрирует мощь комбинирования операторов.
> Get-ChildItem C:\Program Files -Filter "*.exe" -Recurse |
Where-Object {
($_.LastWriteTime.Year -eq (Get-Date).Year) -and ($_.LastWriteTime.Month -ne (Get-Date).Month)
}
Примечание: скобки () вокруг каждого условия используются для группировки и улучшения читаемости, особенно в сложных случаях.
Будьте внимательны с рекурсией:
Если очень много файлов/папок — -Recurse может рекурсивно заходить в десятки тысяч элементов.
Символические ссылки / циклические ссылки — могут вызывать бесконечную рекурсию.
Файлы без прав доступа — могут блокировать выполнение.
4. Создание, управление и безопасное удаление
Создание, копирование и перемещение:
> New-Item -Path "C:\Temp\MyFolder" -ItemType Directory
> Add-Content -Path "C:\Temp\MyFolder\MyFile.txt" -Value "Первая строка"
> Copy-Item -Path "C:\Temp\MyFolder" -Destination "C:\Temp\MyFolder_Copy" -Recurse
Безопасное удаление
Remove-Item — потенциально опасный командлет, поэтому в PowerShell есть встроенные механизмы защиты. Ключ -WhatIf (Что если?): Ваш лучший друг. Он не выполняет команду, а лишь выводит в консоль сообщение о том, что бы произошло.
> Remove-Item C:\Temp\MyFolder -Recurse -Force -WhatIf
Только убедившись, что все верно, убираем -WhatIf и ВЫПОЛНЯЕМ команду
> Remove-Item C:\Temp\MyFolder -Recurse -Force
Введение в функции
Когда одна строка кода превращается в сложный набор команд, который вы хотите использовать снова и снова, наступает время для создания функций.
Как использовать и сохранять функции
Существует три основных способа сделать ваши функции доступными:
Способ 1: Временный (для тестов) Вы можете набрать в консопли или просто скопировать и вставить весь код функции в консоль PowerShell. Функция будет доступна до закрытия этого окна.
Способ 2: Постоянный, но ручной (через .ps1 файл) Это самый распространенный способ для организации и обмена инструментами. Вы сохраняете функцию в файл .ps1 и загружаете ее в сессию, когда она вам нужна.
Способ 3: Автоматический (через профиль PowerShell) Это самый мощный способ для ваших личных, часто используемых инструментов.
Что такое профиль PowerShell? Это специальный скрипт .ps1, который PowerShell автоматически запускает каждый раз при старте. Все, что вы поместите в этот файл — псевдонимы, переменные и, конечно, функции — будет доступно в каждой вашей сессии по умолчанию.
Пример 1: Поиск дубликатов файлов
Давайте пройдем все шаги на примере функции Find-DuplicateFiles.
Шаг 1: Определяем код функции
Шаг 2 (Вариант А): Сохраняем в отдельный файл для ручной загрузки
Сохраняем
> Set-Content -Path ".\Find-DuplicateFiles.ps1" -Value $functionCode
Загружаем
> . .\Find-DuplicateFiles.ps1
Dot Sourcing (. .\Find-DuplicateFiles.ps1): Эта специальная команда выполняет скрипт в текущем контексте, делая все его функции и переменные доступными в вашей консоли.
Вызываем:
> Find-DuplicateFiles -Path "C:\Users\$env:USERNAME\Downloads"
Шаг 2 (Вариант Б): Добавляем в профиль для автоматической загрузки Сделаем эту функцию доступной всегда.
Что такое профиль PowerShell? Это специальный скрипт .ps1, который PowerShell автоматически запускает каждый раз при старте. Все, что вы поместите в этот файл — псевдонимы, переменные и функции — будет доступно в каждой вашей сессии по умолчанию.
Находим путь к файлу профиля. PowerShell хранит его в переменной $PROFILE.
> $PROFILE
Создаем файл профиля, если он не существует:
> if (-not (Test-Path $PROFILE)) { New-Item -Path $PROFILE -Type File -Force }
Добавляем код нашей функции в конец файла профиля.
Add-Content -Path $PROFILE -Value $functionCode
Перезапустите PowerShell (или выполните . $PROFILE), и теперь ваша команда Find-DuplicateFiles будет доступна всегда, как и Get-ChildItem.
Пример 2: Создание ZIP-архива с резервной копией
Код для файла Backup-FolderToZip.ps1:
Детальный разбор функций я сделаю следующих частях.
Справочник командлетов для работы с файловой системой
1. Основные командлеты
Нужно прочитать содержимое текстового файла? Используйте Get-Content. Нужно полностью перезаписать файл новым содержимым? Используйте Set-Content. Нужно добавить строчку в лог-файл, не стирая старые данные? Используйте Add-Content. Нужно проверить, существует ли файл перед записью? Используйте Test-Path.
2. Специализированные командлеты для продвинутых задач
Когда базовых командлетов недостаточно, PowerShell предлагает более специализированные инструменты. Они не дублируют базовые, а расширяют ваши возможности.
Работа с путями (Path)
Join-Path: Безопасно объединяет части пути, автоматически вставляя \.
Split-Path: Разбивает путь на части (папка, имя файла, расширение).
Resolve-Path: Преобразует относительный путь (например, . или ..\files) в полный, абсолютный.
Работа со свойствами и содержимым (Item Properties and Content)
Get-ItemProperty: Получает свойства конкретного файла (например, IsReadOnly, CreationTime).
Set-ItemProperty: Изменяет свойства файла или папки.
Clear-Content: Удаляет всё содержимое из файла, но оставляет сам файл пустым.
Продвинутая навигация (Location Stack)
Push-Location: "Запоминает" текущую директорию и переходит в новую.
Pop-Location: Возвращается в директорию, которую "запомнил" Push-Location.
Управление правами доступа (ACL)
Get-Acl: Получает список прав доступа (ACL) для файла или папки.
Set-Acl: Устанавливает права доступа для файла или папки (сложная операция).
Нужно изменить атрибут файла, например, сделать его «только для чтения»? Используйте Set-ItemProperty. Нужно полностью очистить лог-файл, не удаляя его? Используйте Clear-Content. Нужно временно перейти в другую папку в скрипте, а потом гарантированно вернуться назад? Используйте Push-Location и Pop-Location. Нужно узнать, кто имеет права на доступ к папке? Используйте Get-Acl.
В следующей части мы узнаем, как работать с другими хранилищами данных, такими как реестр Windows, используя те же самые подходы, углубимся в понятие функций, рассмотрим операторы логики и научимся интерактивно взаимодействовать с оболочкой
Философия PowerShell на github:
История и первый командлет
Часть 2: Конвейер (Pipeline), переменные, Get-Member, файл .ps1 и экспорт результатов. Исходники ко второй части:
system_monitor.ps1
Часть 3: Навигация и управление файловой системой.
Исходники к третьей части:
Find-DuplicateFiles.ps1
Backup-FolderToZip.ps1
Полезно? Подпишись.
Понравилось — ставь «+»
Удачи! 🚀
UPD:
Вышла четвертая часть Философия PowerShell. Часть 4. Интерактивная работа: Out-ConsoleGridView