Bagikan melalui


tentang_Pipa

Deskripsi singkat

Menggabungkan perintah ke dalam alur di PowerShell

Deskripsi panjang

Pipa adalah serangkaian perintah yang terhubung oleh operator pipa (|) (ASCII 124). Setiap operator alur mengirimkan hasil perintah sebelumnya ke perintah berikutnya.

Output perintah pertama dapat dikirimkan untuk diproses sebagai masukan ke perintah kedua. Dan output itu dapat dikirim ke perintah lain. Hasilnya adalah rantai perintah yang kompleks atau alur yang terdiri dari serangkaian perintah sederhana.

Misalnya

Command-1 | Command-2 | Command-3

Dalam contoh ini, objek yang Command-1 keluarkan dikirim ke Command-2. Command-2 memproses objek dan mengirimkannya ke Command-3. Command-3 memproses objek-objek dan mengirimkannya ke dalam saluran pemrosesan. Karena tidak ada lagi perintah dalam alur, hasilnya ditampilkan di konsol.

Dalam alur, perintah diproses secara berurutan dari kiri ke kanan. Pemrosesan ditangani sebagai operasi tunggal dan output ditampilkan saat dihasilkan.

Berikut adalah contoh sederhana. Perintah berikut mengambil proses Notepad lalu menghentikannya.

Misalnya

Get-Process notepad | Stop-Process

Perintah pertama menggunakan cmdlet Get-Process untuk mendapatkan objek yang mewakili proses Notepad. Ini menggunakan operator alur (|) untuk mengirim objek proses ke cmdlet Stop-Process, yang menghentikan proses Notepad. Perhatikan bahwa perintah Stop-Process tidak memiliki parameter Nama atau id untuk menentukan proses, karena proses yang ditentukan dikirimkan melalui alur.

Contoh alur ini mendapatkan file teks di direktori saat ini, hanya memilih file yang panjangnya lebih dari 10.000 byte, mengurutkannya berdasarkan panjang, dan menampilkan nama dan panjang setiap file dalam tabel.

Get-ChildItem -Path *.txt |
  Where-Object {$_.Length -gt 10000} |
    Sort-Object -Property Length |
      Format-Table -Property Name, Length

Alur ini terdiri dari empat perintah dalam urutan yang ditentukan. Ilustrasi berikut menunjukkan output dari setiap perintah saat diteruskan ke perintah berikutnya dalam alur.

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

Menggunakan alur

Sebagian besar cmdlet PowerShell dirancang untuk mendukung alur. Dalam kebanyakan kasus, Anda dapat pipa hasil cmdlet Get ke cmdlet lain dari kata benda yang sama. Misalnya, Anda dapat menyalurkan output cmdlet Get-Service ke cmdlet Start-Service atau Stop-Service.

Contoh alur ini memulai layanan WMI di komputer:

Get-Service wmi | Start-Service

Misalnya, Anda dapat menyalurkan output Get-Item atau Get-ChildItem dalam penyedia PowerShell Registry ke cmdlet New-ItemProperty. Contoh ini menambahkan entri registri baru, NoOfEmployees, dengan nilai 8124, ke kunci registri MyCompany.

Get-Item -Path HKLM:\Software\MyCompany |
  New-ItemProperty -Name NoOfEmployees -Value 8124

Banyak cmdlet utilitas, seperti Get-Member, Where-Object, Sort-Object, Group-Object, dan Measure-Object digunakan hampir secara eksklusif dalam alur. Anda dapat menyalurkan jenis objek apa pun ke cmdlet ini. Contoh ini menunjukkan cara mengurutkan semua proses di komputer berdasarkan jumlah handel terbuka di setiap proses.

Get-Process | Sort-Object -Property Handles

Anda dapat menyalurkan objek ke cmdlet pemformatan, ekspor, dan output, seperti Format-List, Format-Table, Export-Clixml, Export-Csv, dan Out-File.

Contoh ini menunjukkan cara menggunakan cmdlet Format-List untuk menampilkan daftar properti untuk objek proses.

Get-Process winlogon | Format-List -Property *

Anda juga dapat menyalurkan output perintah asli ke cmdlet PowerShell. Misalnya:

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

Penting

Aliran Success dan Error mirip dengan stream stdout dan stderr shell lainnya. Namun, stdin tidak tersambung ke alur PowerShell untuk input. Untuk informasi selengkapnya, lihat about_Redirection.

Dengan sedikit latihan, Anda akan menemukan bahwa menggabungkan perintah sederhana ke dalam alur menghemat waktu dan mengetik, dan membuat pembuatan skrip Anda lebih efisien.

Cara kerja alur

Bagian ini menjelaskan bagaimana objek input terikat ke parameter cmdlet dan diproses selama eksekusi alur.

Menerima input alur

Untuk mendukung pipelining, cmdlet penerima harus memiliki parameter yang dapat menerima input pipeline. Gunakan perintah Get-Help dengan opsi Full atau Parameter untuk menentukan parameter cmdlet mana yang menerima input alur.

Misalnya, untuk menentukan parameter cmdlet Start-Service mana yang menerima input alur, ketik:

Get-Help Start-Service -Full

atau

Get-Help Start-Service -Parameter *

Bantuan untuk cmdlet Start-Service menunjukkan bahwa hanya parameter InputObject dan Nama yang menerima input pipeline.

-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

Saat Anda mengirim objek melalui alur ke , PowerShell mencoba mengaitkan objek dengan InputObject dan parameter Nama .

Metode menerima input jalur pipa

Parameter cmdlet dapat menerima input alur dengan salah satu dari dua cara berbeda:

  • ByValue: Parameter menerima nilai yang cocok dengan jenis .NET yang diharapkan atau yang dapat dikonversi ke jenis tersebut.

    Misalnya, parameter Nama menerima input alur berdasarkan nilai. Ini dapat menerima objek string atau objek yang dapat dikonversi ke string.

  • ByPropertyName: Parameter hanya menerima input ketika objek input memiliki properti dengan nama yang sama dengan parameter .

    Misalnya, parameter Nama dapat menerima objek yang memiliki properti Nama . Untuk mencantumkan properti objek, alirkan ke Get-Member.

Beberapa parameter dapat menerima objek berdasarkan nama nilai atau properti, sehingga lebih mudah untuk mengambil input dari alur.

Pengikatan parameter

Saat Anda menyalurkan objek dari satu perintah ke perintah lain, PowerShell mencoba mengaitkan objek yang disalurkan dengan parameter cmdlet penerima.

Komponen pengikatan parameter PowerShell mengaitkan objek input dengan parameter cmdlet sesuai dengan kriteria berikut:

  • Parameter harus menerima input dari alur.
  • Parameter harus menerima jenis objek yang dikirim atau jenis yang dapat dikonversi ke jenis yang diharapkan.
  • Parameter tidak digunakan dalam perintah .

Misalnya, cmdlet Start-Service memiliki banyak parameter, tetapi hanya dua di antaranya, Nama dan InputObject menerima input alur. Parameter Nama menangani string dan parameter InputObject menangani objek layanan. Oleh karena itu, Anda dapat menyalurkan string, objek layanan, dan objek dengan properti yang dapat dikonversi ke string atau objek layanan.

PowerShell mengelola pengikatan parameter seefisien mungkin. Anda tidak dapat menyarankan atau memaksa PowerShell untuk mengikat parameter tertentu. Perintah gagal jika PowerShell tidak dapat mengikat objek yang disalurkan.

Untuk informasi selengkapnya tentang pemecahan masalah kesalahan pengikatan, lihat Menyelidiki Kesalahan Alur nanti di artikel ini.

Pemrosesan satu per satu

Piping objek ke perintah sama seperti menggunakan parameter perintah untuk mengirimkan objek. Mari kita lihat contoh alur. Dalam contoh ini, kita menggunakan alur untuk menampilkan tabel objek layanan.

Get-Service | Format-Table -Property Name, DependentServices

Secara fungsional, ini seperti menggunakan parameter InputObject untuk mengirimkan koleksi objek.

Misalnya, kita dapat menyimpan kumpulan layanan ke variabel yang diteruskan menggunakan parameter InputObject.

$services = Get-Service
Format-Table -InputObject $services -Property Name, DependentServices

Atau kita dapat menyematkan perintah dalam parameter InputObject .

Format-Table -InputObject (Get-Service) -Property Name, DependentServices

Namun, ada perbedaan penting. Saat Anda menyalurkan beberapa objek ke perintah, PowerShell mengirimkan objek ke perintah satu per satu. Saat Anda menggunakan parameter perintah, objek dikirim sebagai objek array tunggal. Perbedaan kecil ini memiliki konsekuensi yang signifikan.

Saat menjalankan alur, PowerShell secara otomatis menghitung jenis apa pun yang mengimplementasikan antarmuka IEnumerable atau rekan generiknya. Item yang terdaftar dikirim melalui alur satu per satu. PowerShell juga menghitung jenis System.Data.DataTable melalui properti .

Ada beberapa pengecualian untuk enumerasi otomatis.

  • Anda harus memanggil metode GetEnumerator() untuk tabel hash, tipe yang mengimplementasikan antarmuka IDictionary atau rekan generiknya, dan tipe System.Xml.XmlNode.
  • Kelas System.String mengimplementasikan IEnumerable, namun PowerShell tidak menghitung objek string.

Dalam contoh berikut, array dan hashtable disalurkan ke cmdlet Measure-Object untuk menghitung jumlah objek yang diterima dari alur. Array memiliki beberapa anggota, dan hashtable memiliki beberapa pasangan kunci-nilai. Hanya array yang dijumlahkan satu per satu.

@(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 :

Demikian pula, jika Anda menyalurkan beberapa objek proses dari cmdlet Get-Process ke cmdlet Get-Member, PowerShell mengirim setiap objek proses, satu per satu, ke Get-Member. Get-Member menampilkan kelas .NET (jenis) objek proses, serta properti dan metodenya.

Get-Process | Get-Member
TypeName: System.Diagnostics.Process

Name      MemberType     Definition
----      ----------     ----------
Handles   AliasProperty  Handles = Handlecount
Name      AliasProperty  Name = ProcessName
NPM       AliasProperty  NPM = NonpagedSystemMemorySize
...

Nota

Get-Member menghilangkan duplikat, jadi jika objek-objek tersebut semuanya berjenis sama, sistem hanya menampilkan satu jenis objek.

Namun, jika Anda menggunakan parameter InputObject pada Get-Member, maka Get-Member menerima array objek System.Diagnostics.Process sebagai satu kesatuan. Ini menampilkan properti dari sebuah array objek. (Perhatikan simbol array ([]) setelah nama tipe System.Object.)

Misalnya

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()
...

Hasil ini mungkin bukan yang Anda inginkan. Tetapi setelah Anda memahaminya, Anda dapat menggunakannya. Misalnya, semua objek array memiliki properti Count. Anda dapat menggunakannya untuk menghitung jumlah proses yang berjalan di komputer.

Misalnya

(Get-Process).Count

Penting untuk diingat bahwa objek yang dikirimkan dalam proses alur dikirimkan satu per satu.

Menggunakan perintah asli dalam alur

PowerShell memungkinkan Anda menyertakan perintah eksternal asli dalam alur.

Sebelum PowerShell 7.4, pipa atau pengalihan output dari program asli yang menghasilkan data byte mentah mengonversi output menjadi string .NET. Konversi ini menyebabkan kerusakan output data mentah.

Di PowerShell 7.4 atau yang lebih tinggi, PSNativeCommandPreserveBytePipe fitur eksperimental adalah mainstream. Fitur ini mempertahankan data byte-stream saat mengalihkan aliran stdout perintah asli ke file atau saat memipakan data byte-stream ke aliran stdin dari perintah asli.

Misalnya, menggunakan perintah asli curl Anda dapat mengunduh file biner dan menyimpannya ke disk menggunakan pengalihan.

$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

Anda juga dapat menyalurkan aliran byte data ke aliran stdin dari perintah asli lainnya. Contoh berikut mengunduh file TAR zip menggunakan curl. Data file yang diunduh dialirkan ke perintah tar untuk mengekstrak konten arsip.

# native command output piped to a native command
curl -s -L $uri | tar -xzvf - -C .

Anda juga dapat menyalurkan output byte-stream dari perintah PowerShell ke input perintah asli. Contoh berikut menggunakan Invoke-WebRequest untuk mengunduh file TAR yang sama dengan contoh sebelumnya.

# 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 .

Fitur ini tidak mendukung data byte-stream saat mengalihkan output stderr ke stdout . Saat Anda menggabungkan aliran stderr dan aliran stdout, aliran gabungan tersebut diperlakukan sebagai data string.

Menyelidiki kesalahan alur

Saat PowerShell tidak dapat mengaitkan objek yang disalurkan dengan parameter cmdlet penerima, perintah gagal.

Dalam contoh berikut, kami mencoba memindahkan entri registri dari satu kunci registri ke kunci registri lainnya. Cmdlet Get-Item mendapatkan jalur tujuan, yang kemudian disalurkan ke cmdlet Move-ItemProperty. Perintah Move-ItemProperty menentukan jalur saat ini dan nama entri registri yang akan dipindahkan.

Get-Item -Path HKLM:\Software\MyCompany\sales |
Move-ItemProperty -Path HKLM:\Software\MyCompany\design -Name product

Perintah gagal dan PowerShell menampilkan pesan kesalahan berikut:

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

Untuk menyelidikinya, gunakan cmdlet Trace-Command untuk melacak komponen pengikatan parameter PowerShell. Contoh berikut melacak pengikatan parameter saat alur sedang dijalankan. Parameter PSHost menampilkan hasil pelacakan di konsol dan parameter FilePath mengirim hasil pelacakan ke file untuk referensi nanti.

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
}

Hasil pelacakan panjang, tetapi menunjukkan nilai yang terikat ke cmdlet Get-Item dan kemudian nilai bernama terikat ke cmdlet 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`]
...

Terakhir, ini menunjukkan bahwa upaya untuk mengikat jalur ke parameter Tujuan dari Move-ItemProperty gagal.

...
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
...

Gunakan cmdlet Get-Help untuk melihat atribut dari parameter Tujuan .

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

Hasil menunjukkan bahwa Destination hanya menerima input alur pipa "berdasarkan nama properti". Oleh karena itu, objek yang disalurkan harus memiliki properti bernama Destination.

Gunakan Get-Member untuk melihat properti objek yang berasal dari Get-Item.

Get-Item -Path HKLM:\Software\MyCompany\sales | Get-Member

Output menunjukkan bahwa item adalah objek Microsoft.Win32.RegistryKey yang tidak memiliki properti Tujuan. Itu menjelaskan mengapa perintah gagal.

Parameter Jalur menerima input alur berdasarkan nama atau berdasarkan nilai.

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

Untuk memperbaiki perintah, kita harus menentukan tujuan dalam cmdlet dan menggunakan untuk mendapatkan Jalur item yang ingin kita pindahkan.

Misalnya

Get-Item -Path HKLM:\Software\MyCompany\design |
Move-ItemProperty -Destination HKLM:\Software\MyCompany\sales -Name product

Kelanjutan baris intrinsik

Seperti yang telah dibahas, alur adalah serangkaian perintah yang terhubung oleh operator alur (|), biasanya ditulis pada satu baris. Namun, untuk keterbacaan, PowerShell memungkinkan Anda untuk membagi alur di beberapa baris. Ketika operator pipa adalah token terakhir pada baris, parser PowerShell menggabungkan baris berikutnya dengan perintah saat ini untuk melanjutkan konstruksi pipeline.

Misalnya, alur satu baris berikut:

Command-1 | Command-2 | Command-3

dapat ditulis sebagai:

Command-1 |
    Command-2 |
    Command-3

Spasi awal pada baris-baris selanjutnya tidak signifikan. Indentasi meningkatkan keterbacaan.

PowerShell 7 menambahkan dukungan untuk kelanjutan alur dengan karakter alur di awal baris. Contoh berikut menunjukkan bagaimana Anda dapat menggunakan fungsionalitas baru ini.

# 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

Penting

Saat bekerja secara interaktif di shell, menempelkan kode dengan alur di awal baris hanya saat menggunakan Ctrl+V untuk menempelkan. Klik kanan untuk menempelkan baris satu per satu. Karena baris tidak diakhir dengan karakter alur, PowerShell menganggap input selesai dan menjalankan baris tersebut seperti yang dimasukkan.

Lihat juga