HyppÀÀ sisÀltöön

đŸ‘©â€đŸ”Ź Curium

TĂ€rpit

Pipeline

PowerShellissÀ on huomattavan tehokasta hyödyntÀÀ sitÀ, ettÀ merkkijonon sijasta meillÀ on kÀsiteltÀvÀnÀ objekteja. TÀhÀn voi tutustua esimerkiksi seuraavan koodin avulla:

🐳 PowerShell
Get-Item Env:PATH `
    | Select-Object -ExpandProperty Value `
    | ForEach-Object { $_ -Split [System.IO.Path]::PathSeparator } `
    | Resolve-Path `
    | Select-Object -Property Drive, Path, Provider 

Kyseinen koodi ajaa Get-Item komennon Env:PATH:iin. Palautuva entiteetti on tyyppiÀ System.Collections.DictionaryEntry. TÀssÀ tyypissÀ, eli dictionarystÀ, on kentÀt Key ja Value. NÀistÀ meitÀ kiinnostaa vain Value, joka on jatkossa vain tavallinen [System.String] eli merkkijono. Sen sijaan Resolve-Path:n jÀlkeen merkkijonosta muotoutuu merkittÀvÀsti abstraktimpi olio [System.Management.Automation.PathInfo]. TÀmÀ olio sisÀltÀÀ tietoa polusta, asemasta ja palveluntarjoajasta - ja se automaattisesti tarkistaa, onko koko hakemisto olemassa.

Jos haluat muotoilla jotakin kenttÀÀ Select-Object-yhteydessÀ, se onnistuu alla olevalla komennolla. KentÀn nimen sijasta syötÀt @{}-kentÀn eli hashtaulun, jossa on Name ja Expression-kentÀt. Expressinin sisÀllÀ $_ viittaa jokaiseen objektiin pipelinesta eli tÀssÀ tapauksessa PathInfo-olioon.

env_objects.ps1
$custom = @{ Name="Provider"; Expression={$_.Provider.Name} }

Get-Item Env:PATH 
    | Select-Object -ExpandProperty Value 
    | ForEach-Object { $_ -Split [System.IO.Path]::PathSeparator } 
    | Resolve-Path 
    | Select-Object -Property Drive, Path, $custom
🐳 Tuloste
PS/> /app/scripts/env_objects.ps1
Drive Path                        Provider
----- ----                        --------
/     /opt/microsoft/powershell/7 FileSystem
/     /usr/local/sbin             FileSystem
/     /usr/local/bin              FileSystem
/     /usr/sbin                   FileSystem
/     /usr/bin                    FileSystem
/     /sbin                       FileSystem
/     /bin                        FileSystem

Tip

Huomaa, ettÀ yllÀ oleva esimerkki on tarpeettoman monimutkainen tÀhÀn use caseen. Se on esillÀ, koska ympÀristömuuttuja PATH on meille jo entuudestaan tuttu. Jos haluat yksinkertaisesti listata, mitÀ PATH sisÀltÀÀ, riittÀÀ kÀyttöjÀrjestelmÀn mukaan jompi kumpi seuraavista riveistÀ:

$env:PATH -Split ":"  # Linux
$env:PATH -Split ";"  # Windows

TehtÀvÀt

TehtÀvÀ: Pingviinien laskeminen

PowerShellissÀ pipeline siirtÀÀ datan objektin muodossa. Joskus se on ihan vain System.String, joskus se edustaa jotakin spesifiÀ luokkaa. Huomaa, ettÀ aiemmin oppimassamme BashissÀ data on aina tekstirivejÀ. Jos haluaisit parsia sarakkeita, joudut kÀyttÀmÀÀn awk-työkalua tai vastaavaa.

SelvitÀ, mitÀ kukin rivi alla olevassa koodissa tekee. Tutki, mitÀ dataa kukin komento saa ja mitÀ se palauttaa. MikÀ olio on kyseeessÀ missÀkin vÀlissÀ?

Koodirivit on valmiiksi numeroitu. KÀytÀ kyseisiÀ numeroita viittaamaan riveihin ja kirjoita vastauksesi erilliseen moniriviseen kommenttiblokkiin. Halutessasi voit kirjoittaa dokumentaation esimerkiksi erilliseen Markdown-tiedostoon ja viitata siihen.

penguins.ps1
$URL = "https://raw.githubusercontent.com/mwaskom/seaborn-data/master/penguins.csv"
$df = Invoke-WebRequest -Uri $URL               # 1
    | Select-Object -ExpandProperty Content     # 2
    | ConvertFrom-Csv                           # 3
    | Group-Object -Property species            # 4
    | Sort-Object -Property Count -Descending   # 5
    | Select-Object -Property Name, Count       # 6

<#
1: Select-Object
    Dokumentoi tÀhÀn ensimmÀinen komento eli Select-Object.
    TekstiÀ tekstiÀ tekstiÀ ja tekstiÀ et cetera et cetera.
    TekstiÀ tekstiÀ tekstiÀ ja tekstiÀ et cetera et cetera.
2: ConvertFromCsv
    ...
6: Select-Object
    ...
#>

Write-Output $df
Vinkki

Kommentoi muut paitsi ensimmÀinen rivi blokista pois ja lisÀÀ seuraavaksi elementiksi pipelineen | Get-Member tai | Format-Table. Sitten tÀÀ tÀmÀ seuraavalle riville ja niin edelleen.

TehtÀvÀ: Suurimmat ohjelmat

Luo skripti, joka tulostaa n kappaletta suurimpia binÀÀritiedostoja /usr/bin-hakemistossa. Vakio n = 5, mutta kÀyttÀjÀ voi syöttÀÀ sen. Esimerkki kÀytöstÀ alla:

🐳 PowerShell
PS/> /app/scripts/largest_binaries.ps1 -n 7
Name       Size (MB)
----       ---------
gpg2           1.124
bash           0.938
ssh            0.825
openssl        0.818
gpgsm          0.566
gpgv2          0.520
ssh-keygen     0.499
TehtÀvÀ: Duplikaattitiedostojen luominen

TÀmÀ tehtÀvÀ toimii esiasteena seuraavalle tehtÀvÀlle. Luo skripti, joka kirjoittaa tiedostoihin sisÀltöÀ siten, ettÀ osa tiedostoista on tarkoituksella toistensa kopioita. Osa tiedostoista tulee sen sijaan olla uniikkeja. Voit kÀyttÀÀ apuna seuraavanlaista jakoa:

add_duplicates.ps1
$duplicateFiles = @(
    "$DTEMP/foo.txt",
    "$DTEMP/foo_copy.txt",
    "$DTEMP/nested/foo_copy_nested.txt"
)

$uniqueFiles = @(
    "$DTEMP/unicorn_a.txt",
    "$DTEMP/nested/unicorn_b.txt"
)

Lopulta ohjelmaa tulisi voida kÀyttÀÀ seuraavanlaisesti:

🐳 PowerShell
PS /> /app/scripts/add_duplicates.ps1
Duplicate files have been created in: /tmp/20250217_duplicates

PS /> Get-Content /tmp/20250217_duplicates/foo.txt
This is some duplicate content.

PS /> Get-Content /tmp/20250217_duplicates/nested/foo_copy_nested.txt
This is some duplicate content.

PS /> Get-Content /tmp/20250217_duplicates/unicorn_a.txt             
5f976325-d704-403f-8442-66b626989aa0

PS /> Get-Content /tmp/20250217_duplicates/nested/unicorn_b.txt      
e3c216bf-f020-402a-beb4-7e838044776d

Uniikki sisÀltö

UniikkiÀ sisÀltöÀ on helppo luoda Get-Uuid-funktiolla.

TehtÀvÀ: Duplikaattien tunnistaminen

Luo skripti, joka tunnistaa duplikaatit annetussa hakemistossa. MikÀli -Recurse option on annettu, sen tulisi kÀydÀ myös alihakemistot lÀpi. Duplikaatit tulisi tunnistaa tiedoston MD5-hashin perusteella. Lopullisen sovelluksen tulisi vastata Get-Help-komentoon seuraavaa sisÀltöÀ myötÀilevÀllÀ tavalla:

NAME
/app/scripts/find_duplicates.ps1

SYNOPSIS
    Find duplicate files in a directory (or recursively in subdirectories).

SYNTAX
    /app/scripts/find_duplicates.ps1 [[-Path] <String>] [-Recurse] [<CommonParameters>]

Testaa ohjelma sekÀ -Recurse parametrilla ettÀ ilman kÀyttÀen kohteena aiemman add_duplicates.ps1-skriptin luomaa hakemistoa. Esimerkki alla:

🐳 PowerShell
PS /> /app/scripts/find_duplicates.ps1 /tmp/20250217_duplicates/ -Recurse
WARNING: Duplicate files found:

FullName                                            Hash
--------                                            ----
/tmp/20250217_duplicates/foo_copy.txt               EAACC3FB772804B7670032CF1ACCBF79
/tmp/20250217_duplicates/foo.txt                    EAACC3FB772804B7670032CF1ACCBF79
/tmp/20250217_duplicates/nested/foo_copy_nested.txt EAACC3FB772804B7670032CF1ACCBF79

Warning

Varmista, ettÀ uniikit /tmp/yyyymmdd_duplicates/unicorn_a.txt ja .../nested/unicorn_b.txt eivÀt nÀy duplikaatteina.

Tip

Muistathan yhÀ ajaa Invoke-ScriptAnalyzer-komennon kaikille skripteillesi! TÀmÀn skriptin kohdalla tulet huomaamaan varoituksen: The Algorithm parameter of cmdlet 'Get-FileHash' was used with the broken algorithm 'MD5'.

MD5 ei suinkaan ole rikki, mutta se ei ole kryptaukseen liittyvissÀ yhteyksissÀ riittÀvÀn vahva. Voit sivuuttaa tÀmÀn varoituksen lisÀÀmÀllÀ seuraavat rivit skriptisi alkuun:

[Diagnostics.CodeAnalysis.SuppressMessage(
"PSAvoidUsingBrokenHashAlgorithms",
"",
Justification = "We are using MD5 for non-cryptographic purposes."
)]