Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Краткое описание
Объединение команд в конвейеры в PowerShell
Длинное описание
Конвейер — это ряд команд, подключенных операторами конвейера (|) (ASCII 124). Каждый оператор конвейера отправляет результаты предыдущей команды в следующую команду.
Выходные данные первой команды можно отправить для обработки в качестве входных данных во вторую команду. И эти выходные данные можно отправить в еще одну команду. Результатом является сложная цепочка команд или конвейер , состоящий из ряда простых команд.
Например
Command-1 | Command-2 | Command-3
В этом примере объекты, которые излучает Command-1, отправляются в Command-2.
Command-2 обрабатывает объекты и отправляет их в Command-3.
Command-3 обрабатывает объекты и отправляет их по конвейеру. Так как в конвейере больше команд нет, результаты отображаются в консоли.
В конвейере команды обрабатываются слева направо. Процесс выполняется как одна операция, и выходные данные отображаются по мере его создания.
Вот простой пример. Следующая команда получает информацию о процессе Блокнота, а затем останавливает его.
Например
Get-Process notepad | Stop-Process
Первая команда использует командлет Get-Process для получения объекта, представляющего процесс «Блокнот». Он использует оператор конвейера (|), чтобы передать объект процесса в командлет Stop-Process, который останавливает процесс Блокнота. Обратите внимание, что команда Stop-Process не имеет параметра Name или Id для указания процесса, так как указанный процесс отправляется через конвейер.
Этот пример конвейера получает текстовые файлы в текущем каталоге, выбирает только те файлы, которые имеют длину более 10 000 байтов, сортируют их по длине и отображают имя и длину каждого файла в таблице.
Get-ChildItem -Path *.txt |
Where-Object {$_.Length -gt 10000} |
Sort-Object -Property Length |
Format-Table -Property Name, Length
Этот конвейер состоит из четырех команд в указанном порядке. На следующем рисунке показаны выходные данные каждой команды, передаваемой в следующую команду в конвейере.
Get-ChildItem -Path *.txt
| (FileInfo objects for *.txt)
V
Where-Object {$_.Length -gt 10000}
| (FileInfo objects for *.txt)
| ( Length > 10000 )
V
Sort-Object -Property Length
| (FileInfo objects for *.txt)
| ( Length > 10000 )
| ( Sorted by length )
V
Format-Table -Property Name, Length
| (FileInfo objects for *.txt)
| ( Length > 10000 )
| ( Sorted by length )
| ( Formatted in a table )
V
Name Length
---- ------
tmp1.txt 82920
tmp2.txt 114000
tmp3.txt 114000
Использование конвейеров
Большинство командлетов PowerShell предназначены для поддержки конвейеров. В большинстве случаев можно канал результаты командлета Get к другому командлету того же существительного.
Например, можно передать выходные данные командлета Get-Service в командлеты Start-Service или Stop-Service.
В этом примере конвейер запускает службу WMI на компьютере:
Get-Service wmi | Start-Service
Например, можно передать выходные данные Get-Item или Get-ChildItem в поставщике реестра PowerShell в командлет New-ItemProperty. В этом примере добавляется новая запись реестра NoOfEmployeesс значением 8124в раздел реестра MyCompany.
Get-Item -Path HKLM:\Software\MyCompany |
New-ItemProperty -Name NoOfEmployees -Value 8124
Многие командлеты служебной программы, такие как Get-Member, Where-Object, Sort-Object, Group-Objectи Measure-Object, используются почти исключительно в конвейерах. Вы можете передать любой тип объекта в эти командлеты. В этом примере показано, как сортировать все процессы на компьютере по количеству открытых дескрипторов в каждом процессе.
Get-Process | Sort-Object -Property Handles
Объекты можно передать в командлеты форматирования, экспорта и вывода, например Format-List, Format-Table, Export-Clixml, Export-Csvи Out-File.
В этом примере показано, как использовать командлет Format-List для отображения списка свойств для объекта процесса.
Get-Process winlogon | Format-List -Property *
Вы также можете передать выходные данные встроенных команд в командлеты PowerShell. Например:
PS> ipconfig.exe | Select-String -Pattern 'IPv4'
IPv4 Address. . . . . . . . . . . : 172.24.80.1
IPv4 Address. . . . . . . . . . . : 192.168.1.45
IPv4 Address. . . . . . . . . . . : 100.64.108.37
Важный
Потоки успеха и потоки ошибок аналогичны потокам stdout и stderr других оболочек. Однако stdin не подключен к конвейеру PowerShell для ввода. Дополнительные сведения см. в разделе about_Redirection.
С небольшой практикой вы обнаружите, что объединение простых команд в конвейеры экономит время и ввод текста, а также делает скрипт более эффективным.
Как работают конвейеры
В этом разделе объясняется, как входные объекты привязаны к параметрам командлета и обрабатываются во время выполнения конвейера.
Принимает входные данные конвейера
Для поддержки конвейерной настройки командлет-получатель должен иметь параметр, принимающий входные данные конвейера. Используйте команду Get-Help с опциями Full или Параметр, чтобы определить, какие параметры командлета принимают входные данные из конвейера.
Например, чтобы определить, какие параметры командлета Start-Service могут принимать данные из конвейера, выполните:
Get-Help Start-Service -Full
или
Get-Help Start-Service -Parameter *
В справке командлета Start-Service показано, что только параметры InputObject и Name принимают входные данные конвейера.
-InputObject <ServiceController[]>
Specifies ServiceController objects representing the services to be started.
Enter a variable that contains the objects, or type a command or expression
that gets the objects.
Required? true
Position? 0
Default value None
Accept pipeline input? True (ByValue)
Accept wildcard characters? false
-Name <String[]>
Specifies the service names for the service to be started.
The parameter name is optional. You can use Name or its alias, ServiceName,
or you can omit the parameter name.
Required? true
Position? 0
Default value None
Accept pipeline input? True (ByPropertyName, ByValue)
Accept wildcard characters? false
При отправке объектов через конвейер в Start-ServicePowerShell пытается связать объекты с параметрами InputObject и Name.
Методы приема входных данных конвейера
Параметры командлетов могут принимать данные, передаваемые через конвейер, одним из двух способов.
ByValue: параметр принимает значения, соответствующие ожидаемому типу .NET или которые можно преобразовать в этот тип.
Например, параметр имени объекта
Start-Serviceпринимает входные данные конвейера по значению. Он может принимать строковые объекты или объекты, которые можно преобразовать в строки.ByPropertyName: параметр принимает входные данные только в том случае, если входной объект имеет свойство того же имени, что и параметр.
Например, параметр Name
Start-Serviceможет принимать объекты с свойством Name. Чтобы получить список свойств объекта, передайте его вGet-Member.
Некоторые параметры могут принимать объекты как по значению, так и по имени свойства, что упрощает прием входных данных из конвейера.
Привязка параметров
При передаче объектов по каналу из одной команды в другую PowerShell пытается связать передаваемые объекты с параметром принимающего cmdlet.
Компонент привязки параметров PowerShell связывает входные объекты с параметрами командлета в соответствии со следующими критериями:
- Параметр должен принимать входные данные из конвейера.
- Параметр должен принять тип отправляемого объекта или тип, который можно преобразовать в ожидаемый тип.
- Параметр не использовался в команде.
Например, командлет Start-Service имеет множество параметров, но только два из них, Name и InputObject, принимают входные данные конвейера. Параметр Name принимает строки, а параметр InputObject принимает объекты сервиса. Таким образом, можно передать строки, объекты службы и объекты со свойствами, которые можно преобразовать в строковые или служебные объекты.
PowerShell управляет привязкой параметров максимально эффективно. Вы не можете предложить или принудительно привязать PowerShell к конкретному параметру. Команда завершается ошибкой, если PowerShell не может сопоставить объекты, переданные через конвейер.
Дополнительные сведения об устранении ошибок привязки см. в разделе исследовании ошибок конвейера далее в этой статье.
Поэтапная обработка
Передача объектов по конвейеру в команду напоминает использование параметра команды для отправки объектов. Рассмотрим пример конвейера. В этом примере конвейер используется для отображения таблицы объектов службы.
Get-Service | Format-Table -Property Name, DependentServices
Функционально это похоже на использование параметра InputObjectFormat-Table для отправки коллекции объектов.
Например, можно сохранить коллекцию служб в переменную, передаваемую с помощью параметра InputObject.
$services = Get-Service
Format-Table -InputObject $services -Property Name, DependentServices
Или можно внедрить команду в параметр InputObject.
Format-Table -InputObject (Get-Service) -Property Name, DependentServices
Однако есть важное различие. При отправке нескольких объектов в команду PowerShell отправляет объекты в команду одновременно. При использовании параметра команды объекты отправляются в виде одного объекта массива. Это незначительное различие имеет значительные последствия.
При выполнении конвейера PowerShell автоматически перебирает любой тип, реализующий интерфейс IEnumerable или его универсальный аналог. Перечисляемые элементы отправляются по конвейеру по одному за раз. PowerShell также перечисляет типы System.DataTable через свойство Rows.
Существует несколько исключений для автоматического перечисления.
- Необходимо вызвать метод
GetEnumerator()для хэш-таблиц, типов, реализующих интерфейсIDictionaryили его универсальный тип, и типы System.Xml.XmlNode. - Класс System.String реализует
IEnumerable, однако PowerShell не перечисляет строковые объекты.
В следующих примерах массив и хэш-файл передаются в командлет Measure-Object для подсчета количества объектов, полученных из конвейера. Массив содержит несколько элементов, а хеш-таблица содержит несколько пар "ключ-значение". Только один массив перечисляется за один раз.
@(1,2,3) | Measure-Object
Count : 3
Average :
Sum :
Maximum :
Minimum :
Property :
@{"One"=1;"Two"=2} | Measure-Object
Count : 1
Average :
Sum :
Maximum :
Minimum :
Property :
Аналогичным образом, если передать несколько объектов процесса из командлета Get-Process в командлет Get-Member, PowerShell отправляет каждый объект процесса по одному за раз в Get-Member.
Get-Member отображает класс .NET (тип) объектов процесса и их свойства и методы.
Get-Process | Get-Member
TypeName: System.Diagnostics.Process
Name MemberType Definition
---- ---------- ----------
Handles AliasProperty Handles = Handlecount
Name AliasProperty Name = ProcessName
NPM AliasProperty NPM = NonpagedSystemMemorySize
...
Заметка
Get-Member устраняет дубликаты, поэтому если объекты имеют одинаковый тип, он отображает только один тип объекта.
Однако если вы используете []) после имени типа System.Object.)
Например
Get-Member -InputObject (Get-Process)
TypeName: System.Object[]
Name MemberType Definition
---- ---------- ----------
Count AliasProperty Count = Length
Address Method System.Object& Address(Int32 )
Clone Method System.Object Clone()
...
Это может быть не то, что вы намеревались. Но после того как вы понимаете его, вы можете использовать его. Например, все объекты массива имеют свойство Count. Это можно использовать для подсчета количества процессов, выполняемых на компьютере.
Например
(Get-Process).Count
Важно помнить, что объекты, отправляемые по конвейеру, доставляются по одному за раз.
Использование собственных команд в конвейере
PowerShell позволяет включать собственные внешние команды в конвейер.
Перед PowerShell 7.4 пилинг или перенаправление выходных данных из собственной программы, которая выводит необработанные данные байтов, преобразовывает выходные данные в строки .NET. Это преобразование вызвало повреждение выходных данных необработанных данных.
В PowerShell 7.4 или более поздней версии экспериментальная функция является основной PSNativeCommandPreserveBytePipe . Эта функция сохраняет данные байт-потока при перенаправлении потока stdout собственной команды в файл или при передаче данных байт-потока в поток stdin собственной команды.
Например, с помощью собственной команды curl можно скачать двоичный файл и сохранить его на диск с помощью перенаправления.
$uri = 'https://github.com/PowerShell/PowerShell/releases/download/v7.3.4/powershell-7.3.4-linux-arm64.tar.gz'
# native command redirected to a file
curl -s -L $uri > powershell.tar.gz
Вы также можете передать данные байт-потока в поток stdin другой собственной команды. В следующем примере скачивается запакованный TAR-архив с помощью curl. Скачанные данные файла передаются в команду tar для извлечения содержимого архива.
# native command output piped to a native command
curl -s -L $uri | tar -xzvf - -C .
Вы также можете передать выходные данные байтового потока команды PowerShell в входные данные собственной команды. В следующих примерах используется Invoke-WebRequest для скачивания того же ФАЙЛА TAR, что и в предыдущем примере.
# byte stream piped to a native command
(Invoke-WebRequest $uri).Content | tar -xzvf - -C .
# bytes piped to a native command (all at once as byte[])
,(Invoke-WebRequest $uri).Content | tar -xzvf - -C .
Эта функция не поддерживает данные потока байтов при перенаправлении выходных данных stderr в stdout. При объединении stderr и потоков stdout объединенные потоки обрабатываются как строковые данные.
Изучение ошибок конвейера
Если PowerShell не может связать объекты с параметром принимающего командлета, команда завершается ошибкой.
В следующем примере мы пытаемся переместить запись реестра из одного раздела реестра в другой. Командлет Get-Item получает путь назначения, который затем будет передан командлету Move-ItemProperty. Команда Move-ItemProperty указывает текущий путь и имя перемещаемой записи реестра.
Get-Item -Path HKLM:\Software\MyCompany\sales |
Move-ItemProperty -Path HKLM:\Software\MyCompany\design -Name product
Команда завершается ошибкой, и PowerShell отображает следующее сообщение об ошибке:
Move-ItemProperty : The input object can't be bound to any parameters for
the command either because the command doesn't take pipeline input or the
input and its properties do not match any of the parameters that take
pipeline input.
At line:1 char:23
+ $a | Move-ItemProperty <<<< -Path HKLM:\Software\MyCompany\design -Name p
Для изучения используйте командлет Trace-Command для трассировки компонента привязки параметров PowerShell. В следующем примере отслеживается привязка параметров во время выполнения конвейера. Параметр
Trace-Command -Name ParameterBinding -PSHost -FilePath debug.txt -Expression {
Get-Item -Path HKLM:\Software\MyCompany\sales |
Move-ItemProperty -Path HKLM:\Software\MyCompany\design -Name product
}
Результаты трассировки являются длинными, но они показывают значения, привязанные к командлету Get-Item, а затем именованные значения, привязанные к командлету Move-ItemProperty.
...
BIND NAMED cmd line args [`Move-ItemProperty`]
BIND arg [HKLM:\Software\MyCompany\design] to parameter [Path]
...
BIND arg [product] to parameter [Name]
...
BIND POSITIONAL cmd line args [`Move-ItemProperty`]
...
Наконец, показано, что попытка привязать путь к параметру назначения не удалась Move-ItemProperty.
...
BIND PIPELINE object to parameters: [`Move-ItemProperty`]
PIPELINE object TYPE = [Microsoft.Win32.RegistryKey]
RESTORING pipeline parameter's original values
Parameter [Destination] PIPELINE INPUT ValueFromPipelineByPropertyName NO
COERCION
Parameter [Credential] PIPELINE INPUT ValueFromPipelineByPropertyName NO
COERCION
...
Используйте командлет Get-Help для просмотра атрибутов параметра назначения .
Get-Help Move-ItemProperty -Parameter Destination
-Destination <String>
Specifies the path to the destination location.
Required? true
Position? 1
Default value None
Accept pipeline input? True (ByPropertyName)
Accept wildcard characters? false
В результатах показано, что назначения принимает входные данные конвейера только по имени свойства. Таким образом, канализированный объект должен иметь свойство под названием Назначение.
Используйте Get-Member, чтобы просмотреть свойства объекта, исходящего из Get-Item.
Get-Item -Path HKLM:\Software\MyCompany\sales | Get-Member
В выходных данных показано, что элемент является объектом Microsoft.Win32.RegistryKey, у которого нет свойства Destination. Это объясняет, почему команда завершилась сбоем.
Параметр пути принимает входные данные конвейера либо по значению, либо по имени.
Get-Help Move-ItemProperty -Parameter Path
-Path <String[]>
Specifies the path to the current location of the property. Wildcard
characters are permitted.
Required? true
Position? 0
Default value None
Accept pipeline input? True (ByPropertyName, ByValue)
Accept wildcard characters? true
Чтобы исправить команду, необходимо указать место назначения в командлете Move-ItemProperty и использовать Get-Item для получения пути элемента, который мы хотим переместить.
Например
Get-Item -Path HKLM:\Software\MyCompany\design |
Move-ItemProperty -Destination HKLM:\Software\MyCompany\sales -Name product
Встроенное продолжение строки
Как уже упоминалось, конвейер представляет собой ряд команд, подключенных операторами конвейера (|), обычно написанными в одной строке. Однако для удобства чтения PowerShell позволяет разделить конвейер по нескольким строкам. Когда оператор канала является последним маркером в строке, средство синтаксического анализа PowerShell присоединяет следующую строку к текущей команде, чтобы продолжить построение конвейера.
Например, следующий однострочный конвейер:
Command-1 | Command-2 | Command-3
можно записать как:
Command-1 |
Command-2 |
Command-3
Пробелы в начале последующих строк не имеют значения. Отступы улучшают читаемость.
PowerShell 7 добавляет поддержку продолжения конвейеров с символом конвейера в начале строки. В следующих примерах показано, как использовать эту новую функцию.
# Wrapping with a pipe at the beginning of a line (no backtick required)
Get-Process | Where-Object CPU | Where-Object Path
| Get-Item | Where-Object FullName -Match "AppData"
| Sort-Object FullName -Unique
# Wrapping with a pipe on a line by itself
Get-Process | Where-Object CPU | Where-Object Path
|
Get-Item | Where-Object FullName -Match "AppData"
|
Sort-Object FullName -Unique
Важный
При интерактивной работе в оболочке вставка кода с конвейерами в начале строки возможна только при использовании комбинации клавиш Ctrl+V. Операции вставки правой кнопкой мыши вставляют строки одновременно. Поскольку строка не заканчивается символом конвейера, PowerShell считает входные данные завершенными и выполняет эту строку как введено.
См. также
PowerShell