Дисклеймер
Статья не претендует на статус полного руководства по PowerShell; для этих целей есть официальные ресурсы Microsoft и множество других источников. Я описываю только те команды и приёмы, которые использую сам.
Я излагаю материал в силу своего понимания и знаний. Никто не застрахован от ошибок.
Вместо вступления
Я всю жизнь пользуюсь Windows, но с пятнадцати лет так или иначе администрирую серверы с OS Linux (преимущественно Debian и Ubuntu).
И так получилось, что команды Bash мне намного привычнее, чем команды Cmd или PowerShell.
Однако, даже на Windows чаще удобнее воспользоваться cli-инструментами и не искать “супер крутую бесплатную программу без регистрации и СМС”.
В Windows у нас есть два варианта: морально устаревший cmd (just IMHO), а также развивающийся и навороченный PowerShell. О нём, а точнее о его командах, и пойдёт речь.
Для некоторых команд я приведу аналогичную строку для Bash. Для других такого аналога не будет, если объяснение различий и нюансов потребует слишком много текста.
Статья должна оставаться удобной шпаргалкой и не разрастаться в полноценное руководство по переучиванию с Bash на PowerShell.
Для некоторых команд я приведу официальные алиасы (я сам, как и вы наверное, не люблю нажимать лишние кнопки на клавиатуре там, где этого можно не делать). Для других команд вы сможете сделать свои алиасы при необходимости.
Я сознательно оформляю шпаргалку в виде списка и избегаю таблиц. Таблицы в Markdown нестабильны и к тому же неудобны для редактирования со скринридером.
Немного теории
PowerShell - объектно-ориентированная оболочка и объектно-ориентированный скриптовый язык, а это значит, что результатом команды часто является объект со свойствами и даже методами, а не сырой текст, как в Bash или Zsh.
Чтобы посмотреть структуру объекта, который возвращает та или иная команда PowerShell, используйте вот такую конструкцию:
<command> | Get-Member
Команда выведет список всех свойств и методов объекта, возвращаемого командой до конвеера (вертикальной черты).
Например, команда Get-Process без параметров возвращает информацию обо всех процессах в системе.
Get-Process | Get-Member
Эта команда выведет список всех свойств и методов объекта с информацией о процессе в виде таблицы. Важно: в выводе команды может показаться, что через трубку (вертикальную черту) передался только один объект, а не массив всех объектов процессов. Это не так: просто элементы коллекции передаются следующей команде по одному.
Таблицы не всегда удобны для чтения со скринридером, поэтому результат можно направить в команду форматирования в виде списка:
Get-Process | Get-Member | Format-List
На выходе получим уже плоское представление в виде списка, которое удобнее читать со скринридером.
Или можно короче, используя официальные алиасы:
Get-Process | gm | fl
Файлы и директории
Команды для работы с файлами и директориями.
Навигация
Команды навигации по файловой системе.
Get-Location- получить путь к текущей рабочей директории.Официальные алиасы:
pwd,gl.Команда возвращает объект, а не строку. Для получения чистой строки используйте
(pwd).Pathили$PWD.Path.Get-ChildItem- вывести список файлов и папок в рабочей директории.Аналог
lsв Bash.Официальные алиасы:
ls,dir,gci.По умолчанию выводится таблица. Чтобы вывести только имена (аналогично
ls -1) списком, можно использоватьGet-ChildItem | Select-Object -ExpandProperty Name, что очень длинно.Короче можно так:
(ls).Name,ls -Name, или более грамотно с точки зрения PowerShellls | select -Expand Name.Чтобы отобразить скрытые и системные файлы и папки (аналог
ls -aв Linux):ls -Force.Как и в Linux, передав относительный или абсолютный путь команде
ls, можно вывести список не только для рабочей (текущей) директории.Можно вывести только файлы
ls -Fileили только директорииls -Directory.Set-Location- сменить рабочую директорию.Аналог
cdв Bash.Официальные алиасы:
cd,sl,chdir.Поведение почти аналогично тому, что в Linux:
cd ..переходит на уровень выше,cd -переходит в предыдущую директорию.Важно: PowerShell запоминает рабочую директорию отдельно для каждого диска. Для точного перехода в корень диска лучше использовать
cd C:/илиcd C:\.Для перехода в корень текущего диска используйте
cd \, для перехода в домашнюю директорию -cd ~.Push-Location- сменить рабочую директорию и запомнить текущую в стеке.Полный аналог
pushdв Bash.Официальные алиасы:
pushd.Pop-Location- сменить рабочую директорию на ту, что сохранена на вершине стека.Полный аналог
popdв Bash.Официальные алиасы:
popd.Get-Location -Stack- получить стек директорий, сохранённых с помощьюPush-Location.Также работает
pwd -Stack.Get-PSDrive- посмотреть список доступных дисков PowerShell.Это не только диски C:, D:, но и другие локации, например Env: как псевдодиск для переменных окружения, HKCU: - как отображение конкретной ветви реестра.
Официально такие диски называются дисками провайдеров PowerShell.
Get-PSProvider- получить список доступных провайдеров PowerShell.Похоже на предыдущую команду
Get-PSDrive, но выводит список провайдеров, а не их точек входа.Существуют стандартные провайдеры, доступные в каждой системе, а также провайдеры, добавляемые модулями PowerShell.
Работа с файлами и директориями
Команды для создания, изменения и удаления файлов и директорий.
New-Item- создать файл (или директорию см. ниже).Аналог
touchв Bash.Официальные алиасы:
ni,mkdir(для директории).Для создания директории используется
ni -ItemType Directoryили более привычный официальный алиасmkdir.Copy-Item- копировать файл или директорию.Аналог
cpв Bash.Официальные алиасы:
cp,cpi,copy.Для копирования директории, как и в Linux, нужен флаг рекурсивного копирования:
cp -Recurse source-folder dest-folder.Move-Item- переместить файл или директорию.Аналог
mvв Bash.Официальные алиасы:
mv,move,mi.Как и в Linux, для перемещения директории флаг рекурсивности не нужен.
Rename-Item- переименовать файл или директорию.Аналог в Bash:
mv.Официальные алиасы:
ren,rni.Remove-Item- удалить файл или директорию.Аналог
rmв Bash.Официальные алиасы:
rm,del,erase,ri.Для удаления директорий нужен флаг рекурсивности:
rm some-folder -Recurse.
Работа с содержимым файла
Команды для работы с содержимым файлов: записать в файл, прочитать из файла, очистить файл, добавить в конец файла.
Get-Content- прочитать содержимое файла.Аналог
cat.Алиасы:
gc,cat,type.Важно: обычный
Get-Contentпередаёт в конвеер каждую строку отдельным объектом. Если важно получить весь файл целиком, используйтеcat -Raw file.txt.Также,
Get-Contentзаменяет в PowerShell командыheadиtail:cat file.txt -Head 10,cat file.txt -Tail 5.Ещё
Get-Contentимеет функциюtail -f:Get-Content log.txt -Tail 5 -Wait.Set-Content- перезаписывает содержимое в файл, стирая старое содержимое.Аналог в Bash: перенаправление в файл с помощью
>.Set-Contentможет принимать текст и через конвеер, как в виде сырого текста, так и в виде массива строк.Для явного указания кодировки можно использовать
Set-Content file.txt "some text" -Encoding Utf8NoBom.Также
Set-Contentпринимает объекты через конвеер, но для читаемого форматированного содержимого лучше использовать специальные команды записи форматированного содержимого в файл.Add-Content- добавляет содержимое в конец файла, не стирая старое содержимое.Аналог в Bash: перенаправление в файл с помощью
>>.Команда принимает содержимое и через конвеер (аналогично
Set-Content).Для явного указания кодировки можно использовать
Set-Content file.txt "some text" -Encoding Utf8NoBom.Аналогично и поведение касательно объектов, переданных через конвеер.
Clear-Content- очищает содержимое файла.Аналоги в Bash:
: > file.txt,truncate -s 0 file.txt.Официальные алиасы:
clc.Эта команда не удаляет файл, но полностью стирает его содержимое.
ПРимечания
Не используйте Set-Content, Add-Content, Get-Content для двоичных файлов без специальных параметров.
Поиск
КОманды поиска файлов и папок, а также поиска и фильтрации содержимого файлов.
ls -Recurse -Filter *.txt- найти рекурсивно все файлы и папки, подходящие под glob “*.txt”.Аналог в Bash:
find . -name "*.txt".Без параметра
-Recurseкоманда будет искать только в текущей директориии, не обходя рекурсивно дочерние.Select-String -Path *.log -Pattern "error"- найти и вывести во всех файлах “*.log” строки, подходящие под паттерн “error”.Аналог
grep "error" *.logв Bash.Официальные алиасы:
sls.По умолчанию
-Pattern- это регулярное выражение. Для простого поиска по подстроке используйте параметр-SimpleMatch.По умолчанию поиск не чувствителен к регистру. Для чувствительного к регистру поиска используйте параметр
-CaseSensitive.
Магия PowerShell: работа с объектами
PowerShell работает с объектами, и было бы упущением не использовать открывающиеся в связи с этим возможности.
Аналогов в Bash нет, поэтому и формат списка команд немного поменяется: каждой команде я выделяю отдельный заголовок.
Все команды для работы с объектами мы будем тестировать на выводе команды Get-Process, которая возвращает список запущенных в системе процессов.
Where-Object - фильтрация объектов
Аналогично grep, find, awk, но по свойствам объектов.
Алиасы: where или просто знак вопроса ?, что менее читаемо, но и буквы экономит.
Например: Get-Process | where CPU -gt 10.
КОманда выше вернёт только объекты процессов, у которых свойство CPU имеет значение большее, чем 10.
Подробный разбор:
Get-Processвозвращает коллекцию объектов, каждый из которых описывает один процесс в операционной системе.whereфильтрует объекты по условию и пропускает в конвеер дальше (или на экран) только те, которые подошли под условие.CPU- одно из свойств объекта процесса.-gt 10- условие: “значение указанного свойства должно быть строго больше 10”.
Ещё несколько примеров. Если вы дочитали до этого места, назначения этих команд должны быть вам понятны.
ls | where Extension -eq ".txt"ls | where Length -gt 1MBls | where LastWriteTime -gt (Get-Date).AddDays(-7)Get-Service | where Status -eq "Running"
Select-Object - выбрать поля объекта
Примерно аналогично cut, но по свойствам объектов.
Алиас: select.
Например: Get-Process | select Name, Id, CPU.
Команда выше выберет из каждого объекта процесса только поля Name, Id, CPU и создаст новые объекты только с этими полями.
Если вывод направить в конвеер, то следующая команда не получит ничего лишнего, только указанные свойства. При выводе на экран получится красивая таблица.
А ещё можно так: Get-Process | select -Expand Name.
Параметр -Expand или его полная форма -ExpandProperty позволяет отдать не объекты с единственным полем Name, а коллекцию строк, уже без объектов вовсе.
Sort-Object - сортировка объектов
Наверное аналогично sort в Linux, но всё же далеко по смыслу, так как работает с объектами.
Всё же это ближе к сортировкам объектов в массиве в языках программирования.
Алиас: sort.
Например: Get-Process | sort CPU.
Команда выше выведет список процессов, отсортированный по возрастанию значения свойства CPU.
Для сортировки по убыванию (актуально для CPU) используйте Get-Process | sort CPU -Descending.
Вот ещё несколько примеров из реальной практики:
ls | sort Length -Descendingls | sort LastWriteTime -DescendingGet-Service | sort Status, Name
Как видите, сортировать можно и по нескольким свойствам. Тогда сначала объекты будут отсортированы по первому свойству (в нашем примере: по статусу), а затем, уже в рамках этой сортировки - по имени.
Measure-Object - посчитать
Прямого единственного аналога из Linux не придумал.
Алиас: measure.
Посчитать можно многое и по-разному, так что примеры расскажут о команде лучше слов.
ls | Measure-Object - посчитать количество файлов и папок в текущей директории.
ls -File | Measure-Object Length -Sum - посчитать суммарный размер файлов в текущей директории (это не полный аналог du).
Полный аналог du выглядит вот так:
ls -Recurse -File | measure Length -Sum.
А ещё measure умеет много других полезных показателей.
Например команда ls -Recurse -File | measure Length -Sum -Average -Minimum -Maximum -StandardDeviation, запущенная в корне моего Dev Drive, очень долго думала и показала такой вывод:
Count : 328156
Average : 109012,413608162
Sum : 35773077600
Maximum : 1576629248
Minimum : 0
StandardDeviation : 5101472,38548372
Property : LengthЭто очевидно круче, чем wc в Linux.
Group-Object - сгруппировать
Аналогично sort | uniq -c В Linux, но опять же по свойству объекта.
Например: ls -File | group Extension.
Команда выше выведет список файлов, сгруппированный по расширениям, показав ещё и количество файлов с таким расширением.
На мой взгляд, подобное нужно гораздо реже, чем остальные команды работы с объектами, но пригодиться может.
Ещё пример: вывести службы Windows, сгруппированные по статусу. Тут мне в первую очередь было интересно посмотреть их количество.
Get-Service | group Status
Foreach-Object - выполнить действие для каждого объекта
Алиас: знак процента %.
Это аналог цикла foreach в некоторых языках программирования или нечто аналогичное for item in collection: ... в Python.
Здесь важно сказать про переменную $_, которая представляет текущий объект в подобных циклах.
Например, вывести красивую таблицу вида “имя файла и размер” можно так: ls *.txt | % { "File: $($_.Name), Size: $($_.Length)" }.
Магия на примерах
- Найти и вывести 10 самых больших файлов, начиная с текущей директории рекурсивно:
ls -Recurse -File | sort Length -Descending | select -First 10 FullName, Length. - Все .log файлы больше 10 мб:
ls -Recurse -File -Filter *.log | where Length -gt 10MB | select FullName, Length. - Посчитать общий размер mp3 файлов:
ls -Recurse -File -Filter *.mp3 | measure Length -Sum. - Найти топ 10 самых тяжёлых по CPU процессов и вывести только имя процесса, его PID и потребление CPU:
Get-Process | where CPU -gt 1 | sort CPU -Descending | select -First 10 Name, Id, CPU.
Форматирование для вывода на экран
Наверняка вы уже пробовали запускать команды из этой статьи и видели, что вывод получается красивым, форматированным.
Этим форматированием можно управлять. Я даже упоминал об этом во вступлении.
Format-Tableилиft- вывести данные на экран в виде таблицы.Это менее удобно для чтения со скринридером, но полезно для визуального просмотра или для красивых скриншотов.
Format-Listилиfl- вывести данные в виде списка.Это визуально менее красиво, занимает намного больше строк, но очень удобно для навигации и изучения при помощи скринридера.
Format-Wideилиfw- вывод данных в несколько столбцов (примерно как командаlsв Linux размещает имена в несколько столбцов).Format-Customилиfc- кастомное форматирование.Внимание! Без дополнительных параметров даёт крайне “шумный” вывод и не рекомендуется к использованию.
За то позволяет глубже изучать свойства и методы объектов, вложенных в том числе.
Как превратить объекты в текст
ДЛя этого существуют две команды: Out-String и Out-File.
Как понятно из их названий, первая превращает текст в строку, и дальше по конвееру или на экран попадает уже не объект, а строка.
Вторая же действует аналогично, но позволяет сохранить данные в файл.
Для перенаправления данных в файл также работают привычные по Bash операторы > и >>, но их поведение не всегда одинаково и предсказуемо, поэтому Out-String и Out-File предпочтительнее.
Также, существует команда Tee-Object (алиас tee), которая одновременно сохраняет текст в файл и выводит его на экран (либо передаёт дальше в конвеер).
работа с данными: экспорт и импорт
csv
ДАнные можно экспортировать в csv:
Get-Process | Export-Csv processes.csv -NoTypeInformation.
Или дополнить существующий csv, не стирая старые данные:
Get-Process | Export-Csv processes.csv -NoTypeInformation -Append.
csv можно не только экспортировать, но и импортировать:
Import-Csv processes.csv.
После импорта строки csv становятся объектами PowerShell, и с ними можно работать уже привычными способами:
Import-Csv processes.csv | Where-Object Name -eq "pwsh".
Также, можно конвертировать в csv и обратно без сохранения в файл:
Get-Process | Select-Object Name, Id | ConvertTo-Csv -NoTypeInformation
И обратно:
$text | ConvertFrom-Csv.
json
Для json почему-то не существует команд для экспорта в файл и импорта из файла. Однако вот так уже можно:
Get-Process | Select-Object Name, Id, CPU | ConvertTo-Json | Set-Content processes.json -Encoding utf8
И так тоже можно (прочитать обратно):
Get-Content data.json -Raw | ConvertFrom-Json.
Для конвертации в json может пригодиться параметр -Depth. Без него у сложных объектов вложенные свойства могут оказаться обрезанными.
Для чтения json из файла почти всегда предпочтительнее использовать параметр -Raw у Get-Content, чтобы json прочитался и передался в конвеер одним текстом, а не коллекцией отдельных строк.
Экспорт в html
Да-да, я сам удивился, когда в списке команд нашёл это, но можно экспортировать данные в виде таблицы сразу в html.
Get-Process | Select-Object Name, Id, CPU | ConvertTo-Html -Title "Processes" | Set-Content processes.html -Encoding utf8
Таблица получается простая, без оформления и украшений, но для чтения скринридером или сухих отчётов часто и этого достаточно.
Импорт пар ключ-значение
Это не полноценный .env парсер, но файл с содержимым вида
firstName=Kirill
lastName=Belousov
role=developerвполне подходит.
То есть можно сохранить написанное выше как файл data.txt и прочитать вот так:
$data = Get-Content -Raw data.txt | ConvertFrom-StringData.
На выходе в переменную $data будет сохранена хеш-таблица с ключами слева от = и значениями справа.
Работа с процессами
Команды для взаимодействия с процессами в операционной системе.
Прочитав часть статьи выше, вы уже познакомились с базовыми принципами. Поэтому дальше описания будут короче, с меньшим числом примеров.
Помните, что Get-Command - ваш лучший друг и аналог man.
Также, помните, что как и в Linux, доступность информации о некоторых процессах и возможности некоторых команд могут зависеть от полученных привилегий.
Получить список всех запущенных в системе процессов:
Get-Process,psилиgps.Команда принимает позиционный аргумент, с помощью которого можно находить процессы по заданной подстроке. Также, можно передать точное имя процесса с помощью параметра
-Nameили запросить информацию о процессе с конкретным PID при помощи параметра-Id.Запустить новый процесс:
Start-Processилиstart.При помощи параметра
-Waitможно дождаться завершения процесса, а при помощи-ArgumentList- передать список аргументов для вызываемого исполняемого файла.Чтобы запустить процесс от имени администратора, используйте конструкцию
Start-Process exe_name -Verb RunAs.Остановить (убить) процесс:
Stop-Process,killилиspps.Команда останавливает процесс по PID (
kill -Id <PID>) или останавливает один или несколько процессов по имени (kill -Name <exe_name>).Также, команда принимает объекты процессов, например полученные через
Get-Process, через конвеер или через переменную при помощи параметра-InputObject.Ждать завершения процесса:
Wait-Process.Объект процесса можно передать через конвеер, либо указать процесс по
-Nameили по-Id, как и в других командах.Можно задать таймаут ожидания:
Wait-Process -Name notepad -Timeout 10.
Полезные свойства объекта процесса
Все свойства вполне самодокументированы своими именами и не требуют дополнительных пояснений. За это я и люблю PowerShell.
IdProcessNamePathCPUWorkingSetStartTimeHasExitedMainWindowTitle
Примечание
Чтобы одна команда для работы с процессами передала объект дальше в другую команду по конвееру, используйте параметр -PassThru.
Например, возможна такая конструкция:
Start-Process notepad -PassThru | Wait-Process -Timeout 5 -PassThru | Stop-Process.
Команда выше запустит блокнот, подождёт 5 секунд и закроет блокнот.
Буфер обмена
Да, в PowerShell можно взаимодействовать с буфером обмена Windows. Правда работать можно только с текстом, но и этого часто бывает достаточно.
Основных команд всего две:
Get-Clipboard- получить содержимое буфера обмена (только текст).Set-Clipboard- записать текст в буфер обмена.
У второй команды также есть параметр -Append, который позволяет не перезаписать, а дополнить содержимое буфера обмена.
Обе команды конечно же работают через конвеер (Get-Process | Out-String | Set-Clipboard, $params = Get-Clipboard | ConvertFrom-StringData).
Вместо заключения
Не уверен, что эту статью можно когда-нибудь закончить. Я постоянно пополняю её новыми командами, уточнениями, примечаниями по мере того, как сам изучаю особенности оболочки и скриптового языка PowerShell.
Надеюсь, для вас эта шпаргалка окажется полезной.