26.03.2023

Powershell'in dahili fonksiyonları

Powershell'de New-Item cmdlet'ini yeni dosya oluşturmak veya yeni klasör oluşturmak için kullanabiliriz. Bu farkı belirtmek için -ItemType var. Dökümantasyona göre varsayılan bir değeri yok:


Ama garip bir şekilde özellikle belirtmezsek dosya sistemi modunda "dosya" oluşturuyor. Bu varsayılan değer demek değil mi?

Neyse, bu cmdlet'in "ni" alias'ı da var. Gerek tam cmdlet adı, gerek alias'ı ni ile klasör oluşturmak için -ItemType'a Directory değerini vermek yeterli. Hatta ItemType parametresinin yukarıdaki resimde görüldüğü gibi Type alias'ı da var.

PS> New-Item -ItemType Directory -Name YeniKlasor

PS> ni -type directory YeniKlasor

Ama ilginç bir şekilde mkdir veya md komutları da Powershell'de çalışıyor. Önceleri bunları New-Item alias'ları olduğunu sanmıştım ama öyle değilmiş (olsaydı alias için varsayılan parametre değeri nasıl değiltirilir, merak ederdim). Get-Command ile baktığımda şöyle bir sonuç aldım:

PS> Get-Command mkdir

CommandType     Name                      Version    Source
-----------     ----                      -------    ------
Function        mkdir

Meğer mkdir bir Powershell dahili (built-in) komutuymuş. md ise mkdir için bir alias'mış. Diğer dahili komutlar şunlar:

cd..
cd\
ImportSystemModules
pause
help
prompt
Clear-Host
TabExpansion2
Get-Verb
oss

Bunların hepsi için Get-Command ile baktığımızda CommandType sütununda Function yazıyor. Örneğin Write-Host'a Get-Command ile baktığımızda ise CommanType'ı Cmdlet ve Source sütununda modül adı ve Version sütununda da sürüm numarası yazar. Ama Get-Help mkdir'a baktığımda gözüken yardım girdisi, New-Item'in.

PS> Get-Help mkdir

NAME
    New-Item

SYNOPSIS
    Creates a new item.

SYNTAX
    New-Item [[-Path] <System.String[]>] [-Credential <System.Management.Automation.PSCredential>] [-Force] [-ItemType
    <System.String>]
-Name <System.String> [-UseTransaction] [-Value <System.Object>] [-Confirm] [-WhatIf] [<CommonPara
    meters>]

    New-Item [[-Path] <System.String[]>] [-Credential <System.Management.Automation.PSCredential>] [-Force] [-ItemType
    <System.String>]
[-UseTransaction] [-Value <System.Object>] [-Confirm] [-WhatIf] [<CommonParameters>]

Her ne kadar bu yardım girdisinde -ItemType parametresi verilmiş olsa da mkdir ile -ItemType'ı kullanmak aşağıdaki gibi bir hataya sebep oluyor:

PS> mkdir -ItemType file -Name qwer
mkdir : A parameter cannot be found that matches parameter name 'ItemType'.
At line:1 char:7
+ mkdir -ItemType file -Name qwer
+       ~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [mkdir], ParameterBindingException
    + FullyQualifiedErrorId : NamedParameterNotFound,mkdir

Bu arada help'in de bir alias değil de bir dahili komut olması da ilginç.

17.03.2023

Windows Terminal'de 2 farklı powershell profili

Windows Terminal'e birden fazla profil eklemek mümkün. Ama aynı powershell sürümü için birden fazla profil dosyası (powershell oturumu başladığında çalıştırılacak, tek profil durumunda Belgelerim\WindowsPowershell konumunda bulunan *.ps1 uzantılı dosya) nasıl yapılır sorusunun cevabı şu adreste var. Çözüm, için Windows Terminal'in settings.json dosyasını ($env:LOCALAPPDATA\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState konumunda) açıp, yeni yaratılan profilin içine 

"commandline": "powershell.exe -noprofile -noexit -command \"invoke-expression '. ''C:/PsProfile.ps1''' \"",

gibi bir satır eklemek. Burada yeni oturum çalıştırılıdığında C:\PsProfile.ps1 gibi bir dosyanın "dot sourcing" yöntemi ile çalıştırılması sağlanmış (noktaya dikkat!). Bu şekilde farklı prompt'lar, farklı diğer şeyler yaratılabilir. Bundan sonra Windows Terminal ile diğer görünüm ayarları yapılabilir. Örneğin Exhange Management Shell'e bağlanmak için PsProfile.ps1 içine

$cred = Get-Credential -Username "<domain\user>" -Message "Credential to connect to Exchange server"
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://<exchange_url>/PowerShell/ -Credential $cred -Authentication Kerberos
Import-PSSession $Session -Verbose

yazarak Exhange'e özgü bir tema oluşturabiliriz. Her profilin kendine özgü bazı alias'ları, değişkenleri profil dosyasına yazılabilir.

15.03.2023

Manjaro duvar kağıtları, Simon Stalenhag, Sven Dahlstrand, bash ve Powershell

Manjaro KDE'de duvar kağıtları konusunda değişik seçenekler var. Her açılışta zevkinize göre değişik duvar kağıtlarından birini sizin için ayarlayabiliyor.

 

Seçeneklerden biri çok hoşuma gitti. İsmine bakınca koleksiyonun adının Simon Stalenhag olduğunu gördüm. Aratınca bir sürü benzer duvar kağıdının sanal alemde bulunabildiğini farkettim. Hemen Windows'a uyarlamak geldi aklıma. Önce wallpaperflare.com sitesini buldum. Ama buradaki tam boyuttaki resimler maalesef base64 formatında. Bunları powershell ile kaydetmenin  bir yolunu bulamadım. Browser ile statik olarak yüklenmiyorlar, Invoke-WebRequest ile yaptığım işlemde sayfada yer almıyor, muhtemelen bir Javascript ile yerine konuyor. Daha fazla seçenek ararken benzer zevke sahip bir sanal alem bireyi Sven Dahlstrand'ın çalışmasına denk geldim:

ROOT_URL="http://simonstalenhag.se"
MAX_PROCESSES=30
curl -s "${ROOT_URL}" |
grep -Eio "bilderbig[^\"]+\.jpg" |
sort | uniq |
xargs -P "${MAX_PROCESSES}" -n 1 basename |
xargs -P "${MAX_PROCESSES}" -n 1 -I {} curl -z {} -f -O "${ROOT_URL}/bilderbig/{}"

Bunu anlamak bile uzun sürdü. Anladıklarımı özetleyeyim.

- İlk 2 satırda sanatçının çalışmalarının yer aldığı web sayfasının adresi ile xargs komutu ile aynı anda çalıştırılacak süreç sayısı değişkenlere atanmış.

- 3. satırda web sayfasının içeriği alınmış ve 4. satırda içinde bilderbig geçen ve uzantısı .jpg olan adresleri regular expressions ile ayırmış

- 5. satırda bunları sıralayıp içinden tekrarlayan kayıtları silmiş (uniq komutunun önkoşulu girişin sıralı -alfabetik veya değil- olması)

- basename, http://simonstalenhag.se/bilderbig/image.jpg gibi bir adresin içinden sadece image.jpg bilgisini ayırıyor.

- En son satır ise 30 paralel süreçte dosyalar indirilerek her biri aynı isimle mevcut klasöre kaydediliyor.

Bunu powershell ile yapmanın yollarından biri:

$root_url = "http://simonstalenhag.se"
$content = iwr $root_url
$content.Links.href | where {$_ -like "bilderbig*"} | sort | gu | 
% { iwr -uri ($root_url+"/"+$_) -OutFile (Split-Path $_ -Leaf) } 

olabilir. Birebir aynısı değil. 30 paralel işlem yok. curl komutunun -f parametresi, dosyaların olup olmadığını da kontrol ediyor, ben etmedim. Invoke-WebRequest her seferinde üzerine yazar. Bu davranışı değiştirecek bir yol bulamadım ama -OutFile parametresini terk edip, çıkış Out-File cmdlet'ine yönlendirmek (pipe) gibi yöntemlere geçilebilir.

Paralel işlem yapabilmek için de Powershell Core kullanılabilir. Son satırda Foreach-Object'in alias'ı olarak kullanılan "%" sonrasında -Parallel ve hatta -ThrottleLimit eklenebilir:

% -Parallel -ThrottleLimit 30 { ... }

Sonrasında indirilen resimlerden birini duvar kağıdı olarak ayarlamak için daha önce bulduğum Set-Wallpaper fonksiyonu kullanılabilir.

13.03.2023

Birkaç güzel site

Windows terminalde fazla zaman geçirenler için faydalı birkaç site. Eskiden sadece nerdfonts.com vardı. Şimdi programmingfonts.org var. Çeşitli fontları, çeşitli renk temasında, çeşitli programlama dilleri ile deneme imkanı sunan görünümler, sıfır çaba ile test edilebilyor.

Varsayılan Windows Terminal renk temaları çok iç açıcı olmayabilir. Bir renk teması ayarlamak da üstün çabalar gerektirebilir. Bu iki ucun ortasında konumlanan bir çalışma olarak windowsterminalthemes.dev güzel bir çalışma.

Beğendimiz temayı uygulamak için ekranın altındaki mavi "Get theme" butonuna basmak yetmiyor. Bu, sadece json formatındaki yapılandırmayı clipboard'a kopyalıyor. Daha sonra bunu Windows Terminal'e uygulamak için programın json dosyasını favori editörünüzde $env:LOCALAPPDATA\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json dosyasını açarak "schemes" bölümü altına aşağıdaki gibi kopyalanan içeriği yapıştırmak

ve daha sonra da Windows Terminal'in ayarlarından önce "Defaults"a gelip, oradan Appearance'a, daha sonra da Color Scheme'e gelip yeni eklediğimiz temanın adını seçmek gerek.

Nihayet, bir tane de bash promptunu özelleştirmek için bir site. Prompt'ta yer almasını istediğimiz öğeleri seçip, renkleri de ayarladıktan sonra altta çıkan export PS1="..." gibi satırı koplayıp ev klasörümdeki .bashrc dosyasının sonuna yapıştırmak yeterli. Preview bölümü de var.



12.03.2023

oh-my-posh yeni sürüm

Bu oh-my-posh'un derdi ne? Sürekli değişen bir yapı. Önce powershell gallery ile dağıtım, sonra winget ile, sonra Microsoft Store ile, sonra tekrar winget ile. Daha önce powershell terminali özelleştirmek ile ilgili yazıdğım yazıları güncellemektense yeni durumu yazmak istedim.

En son sürüm winget'te. Hatta winget'te de iki farklı sürüm var, bugün itibariyle.

PS> winget

Name       Id                        Version Match                Source

------------------------------------------------------------------------------------------

oh-my-posh XP8K0HKJFRXGCK            Unknown                      msstore

Oh My Posh JanDeDobbeleer.OhMyPosh   14.12.1 Moniker: oh-my-posh  winget

Sanıyorum en güncel sürüm, alttaki satırda görünen winget kaynağından gelen sürüm numarası 14.12.1 olan. Artık powershell modülü olarak gelmediğinden profil dosyasında Install-Module gibi bir işleme gerek yok. Artık $env:LOCALAPPDATA klasörünün altında kuruluyor ve ana bileşen oh-my-posh.exe adında bir exe dosyası. Bir kez oh-my-posh.exe2yi çalıştırdıktan sonra hala Get-PoshThemes komutunu çalıştırarak ya da ohmyposh.dev/docs/themes sitesinden hangi seçeneklerimiz var görebiliyoruz. Hatta Get-PoshThemes'i çalıştırdıktan sonra artık nasıl promptumuzu düzenlememiz gerektiği de belirtiliyor. Profil dosyamızı istediğimiz metin editörü ile (notepad, cods vs) ile açıp içine şöyle bir satır eklememiz yeterli:

oh-my-posh init pwsh --config "$env:POSH_THEMES_PATH/bubbles.omp.json" | Invoke-Expression

Bir sürü tema ve segment var. Segment'ler, prompt'ta gözüken bilgi bölümleri; bulunduğumuz klasör, saat, tarih gibi. Diyelim bir temayı seçtik ama küçük bazı değişiklikler yapmak istiyoruz. Bu durumda $env:POSH_THEMES_PATH/ klasöründeki *.omp.json dosyasının bir kopyasını alarak bu kopyayı düzenleyerek devam edebiliriz. Bu dosyaların yapızı şu şekilde:

{
    "$schema": "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json",
    "blocks": [

        {
            "alignment": "left",
            "segments": [
                {
                ...
                } ,
                ...
             ],
             "type": "prompt"
        },
        {
            "alignment": "right",
            "segments": [
                {
                ...
                } ,
                ...
            ],
            "type": "prompt
        }
    ],
    "final_space": true,
    "version": 2
}
"blocks" bölümünün içine birden fazla virgülle ayrılmış ve küme parantezi içine alınmış alt block öğeleri gelebiliyor. Bu block öğelerini terminalin sağına veya soluna hizalayabiliyoruz. Her block öğesinin içinde birden fazla segment olabiliyor. Segmentler de virgülle ayrılmış ve küme parantezi içine alınmış olacak. Segment'lerin listesi ve kullanımı ile ilgili bütün ayrıntılar için yine ohmyposh.dev sitesinde segments bölüne bakabiliriz. Örneğin içinde bulunulan klasörü yazmak için path segmentine bakalım. Her segment'in olduğu gibi path'in de bir style verisi var. Sadece klasör ağacındaki son altklasörün adını yazmak için "folder", tam yolu yazmak için "full" kullanılabilir. Eğer seçtiğimiz temanın segmentlerini yeterli bulmadıysak veya konumları hoşumuza gitmediyse yerlerini bu kurallara göre değiştirebiliriz.

Her temanın segmentlerinin nasıl görüntüleneceğini belirleyen birkaç küçük özellik var; yazı rengi (foreground), fon rengi (background), öncü (leading_diamond) ve artçı (trailing_diamon) karakterler gibi. Öncü ve artçı karakterler köşeli veya yumuşak hatlara sahip açılış ve kapanış öğeleri olabilir.