د PowerShell او WSL په کارولو سره په وینډوز کې د لینکس کمانډونه یوځای کول

د وینډوز پراختیا کونکو څخه یوه ځانګړې پوښتنه: "ولې لاهم شتون نلري <ВСТАВЬТЕ ТУТ ЛЮБИМУЮ КОМАНДУ LINUX>؟. ایا دا یو پیاوړی سویپ دی less یا پیژندل شوي وسایل grep او یا sed، د وینډوز پرمخ وړونکي په خپل ورځني کار کې دې کمانډونو ته اسانه لاسرسی غواړي.

د لینکس لپاره د وینډوز فرعي سیسټم (WSL) په دې برخه کې یو لوی ګام پورته کړی دی. دا تاسو ته اجازه درکوي د لینوکس کمانډونه له وینډوز څخه د پراکسي کولو له لارې زنګ ووهي wsl.exe (د مثال په توګه ، wsl ls). که څه هم دا د پام وړ پرمختګ دی، دا اختیار د یو شمیر زیانونو سره مخ دی.

  • هر اړخیز اضافه کول wsl ستړیا او غیر طبیعي.
  • په دلیلونو کې د وینډوز لارې تل کار نه کوي ځکه چې بیک سلیشونه د ډایرکټر جلا کونکو پرځای د فرار حروف په توګه تشریح کیږي.
  • په دلیلونو کې د وینډوز لارې په WSL کې اړونده ماونټ نقطې ته نه ژباړل کیږي.
  • د ډیفالټ تنظیماتو ته د WSL پروفایلونو کې د عرف او چاپیریال متغیرونو سره درناوی نه کیږي.
  • د لینکس لارې بشپړول ملاتړ نه کوي.
  • د کمانډ بشپړول نه ملاتړ کیږي.
  • د دلیل بشپړول نه ملاتړ کیږي.

د پایلې په توګه، د لینکس کمانډونه د وینډوز لاندې د دویمې درجې اتباعو په څیر چلند کیږي — او د اصلي قوماندې په پرتله کارول خورا ستونزمن دي. د دوی د حقونو مساوي کولو لپاره، اړینه ده چې لیست شوي ستونزې حل کړي.

د پاورشیل فنکشن ریپرونه

د PowerShell فنکشن ریپرونو سره، موږ کولی شو د کمانډ بشپړول اضافه کړو او د مخکینیو اړتیا له منځه یوسو wslد وینډوز لارې په WSL لارو کې ژباړل. د ګولیو لپاره اساسي اړتیاوې:

  • د هر لینکس کمانډ لپاره باید د ورته نوم سره یو فنکشن ریپر وي.
  • شیل باید د وینډوز لارې پیژني چې د دلیلونو په توګه تیر شوي او د WSL لارو ته یې واړوي.
  • خولۍ باید غږ وکړي wsl د مناسب لینکس کمانډ سره هر پایپ لاین ان پټ ته او د کوم کمانډ لاین دلیلونو تیرولو سره فنکشن ته لیږدول شوی.

څرنګه چې دا نمونه په هر قوماندې پلي کیدی شي، موږ کولی شو د دې ریپرونو تعریف خلاص کړو او په متحرک ډول یې د واردولو لپاره د کمانډونو لیست څخه تولید کړو.

# The commands to import.
$commands = "awk", "emacs", "grep", "head", "less", "ls", "man", "sed", "seq", "ssh", "tail", "vim"
 
# Register a function for each command.
$commands | ForEach-Object { Invoke-Expression @"
Remove-Alias $_ -Force -ErrorAction Ignore
function global:$_() {
    for (`$i = 0; `$i -lt `$args.Count; `$i++) {
        # If a path is absolute with a qualifier (e.g. C:), run it through wslpath to map it to the appropriate mount point.
        if (Split-Path `$args[`$i] -IsAbsolute -ErrorAction Ignore) {
            `$args[`$i] = Format-WslArgument (wsl.exe wslpath (`$args[`$i] -replace "", "/"))
        # If a path is relative, the current working directory will be translated to an appropriate mount point, so just format it.
        } elseif (Test-Path `$args[`$i] -ErrorAction Ignore) {
            `$args[`$i] = Format-WslArgument (`$args[`$i] -replace "", "/")
        }
    }
 
    if (`$input.MoveNext()) {
        `$input.Reset()
        `$input | wsl.exe $_ (`$args -split ' ')
    } else {
        wsl.exe $_ (`$args -split ' ')
    }
}
"@
}

لست $command د وارداتو امرونه تعریفوي. موږ بیا په متحرک ډول د کمانډ په کارولو سره د هر یو لپاره د فنکشن ریپر تولید کوو Invoke-Expression (لومړی د هر ډول عرف په لرې کولو سره چې د فعالیت سره ټکر وکړي).

فنکشن د کمانډ لاین دلیلونو باندې تکرار کوي، د کمانډونو په کارولو سره د وینډوز لارې ټاکي Split-Path и Test-Pathاو بیا دا لارې د WSL لارو ته واړوي. موږ لارې د مرستندویه فعالیت له لارې پرمخ وړو Format-WslArgument، کوم چې موږ به وروسته تعریف کړو. دا ځانګړي کرکټرونه لکه ځایونه او قوسونه تښتي چې بل ډول به غلط تشریح شي.

په نهایت کې ، موږ پیغام ورکوو wsl د پایپ لاین ان پټ او د کمانډ لاین دلیلونه.

د دې ریپرونو سره تاسو کولی شئ خپل د خوښې لینکس کمانډونه په طبیعي ډول د مخکینۍ اضافه کولو پرته زنګ ووهئ wsl او پرته له دې اندیښنه چې څنګه لارې بدلیږي:

  • man bash
  • less -i $profile.CurrentUserAllHosts
  • ls -Al C:Windows | less
  • grep -Ein error *.log
  • tail -f *.log

د کمانډونو اساسی سیټ دلته ښودل شوی ، مګر تاسو کولی شئ په لیست کې په ساده ډول اضافه کولو سره د هر لینکس کمانډ لپاره شیل رامینځته کړئ. که تاسو دا کوډ خپل ته اضافه کړئ پروفایل PowerShell، دا کمانډونه به تاسو ته د PowerShell په هره ناسته کې شتون ولري، لکه د اصلي قوماندې په څیر!

ډیفالټ ترتیبات

په لینکس کې، دا معمول دی چې د ننوتلو پروفایلونو کې عرفونه او/یا د چاپیریال متغیرونه تعریف کړئ، د ډیری کارول شویو کمانډونو لپاره د ډیفالټ پیرامیټونو ترتیب کول (د مثال په توګه، alias ls=ls -AFh او یا export LESS=-i). د غیر متقابل خولۍ له لارې د پراکسي کولو یو له زیانونو څخه wsl.exe - دا چې پروفایلونه نه پورته شوي، نو دا اختیارونه د ډیفالټ لخوا شتون نلري (د مثال په توګه. ls په WSL او wsl ls د پورته تعریف شوي عرف سره به مختلف چلند وکړي).

PowerShell چمتو کوي $PSDefaultParameterValues، د ډیفالټ پیرامیټونو تعریف کولو لپاره معیاري میکانیزم ، مګر یوازې د cmdlets او پرمختللو کارونو لپاره. البته، موږ کولی شو د خپلو شیلونو څخه پرمختللي دندې ترسره کړو، مګر دا غیر ضروري پیچلتیاوې معرفي کوي (د مثال په توګه، PowerShell د جزوي پیرامیټرو نومونو سره تړاو لري) د بیلګې په توګه، -a سره تړاو لري -ArgumentList)، کوم چې به د لینکس کمانډونو سره ټکر وکړي چې جزوي نومونه د دلیلونو په توګه اخلي) او د ډیفالټ تعریف کولو لپاره ترکیب به خورا مناسب نه وي (د ډیفالټ دلیلونو تعریف کول په کلیدي کې د پیرامیټر نوم ته اړتیا لري ، نه یوازې د کمانډ نوم).

په هرصورت، زموږ په شیلونو کې د لږ بدلون سره، موږ کولی شو ورته ماډل پلي کړو $PSDefaultParameterValues، او د لینکس کمانډونو لپاره ډیفالټ اختیارونه فعال کړئ!

function global:$_() {
    …
 
    `$defaultArgs = ((`$WslDefaultParameterValues.$_ -split ' '), "")[`$WslDefaultParameterValues.Disabled -eq `$true]
    if (`$input.MoveNext()) {
        `$input.Reset()
        `$input | wsl.exe $_ `$defaultArgs (`$args -split ' ')
    } else {
        wsl.exe $_ `$defaultArgs (`$args -split ' ')
    }
}

تېرېدل $WslDefaultParameterValues د کمانډ لاین ته، موږ پیرامیټونه له لارې لیږو wsl.exe. لاندې ښیې چې څنګه د ډیفالټ تنظیماتو تنظیم کولو لپاره ستاسو پاور شیل پروفایل کې لارښوونې اضافه کړئ. اوس موږ دا کولی شو!

$WslDefaultParameterValues["grep"] = "-E"
$WslDefaultParameterValues["less"] = "-i"
$WslDefaultParameterValues["ls"] = "-AFh --group-directories-first"

ځکه چې پیرامیټونه وروسته ماډل شوي $PSDefaultParameterValuesتاسو کولی شئ د دوی غیر فعال کول اسانه دي په لنډمهاله توګه د کیلي په نصبولو سره "Disabled" په معنی $true. د جلا هش میز اضافي ګټه د غیر فعال کولو وړتیا ده $WslDefaultParameterValues څخه جلا $PSDefaultParameterValues.

د استدلال بشپړول

PowerShell تاسو ته اجازه درکوي د کمانډ په کارولو سره د دلیل ټریلر ثبت کړئ Register-ArgumentCompleter. باش ځواکمن دی د پروګرام وړ اتوماتیک بشپړولو وسیلې. WSL تاسو ته اجازه درکوي چې له PowerShell څخه bash ته زنګ ووهئ. که موږ وکولی شو د خپلو پاور شیل فنکشن ریپرونو لپاره د دلیل بشپړتیا ثبت کړو او د تکمیلاتو رامینځته کولو لپاره باش ته زنګ ووهو ، موږ د بش په څیر د ورته دقیقیت سره د بشپړ دلیل بشپړول ترلاسه کوو!

# Register an ArgumentCompleter that shims bash's programmable completion.
Register-ArgumentCompleter -CommandName $commands -ScriptBlock {
    param($wordToComplete, $commandAst, $cursorPosition)
 
    # Map the command to the appropriate bash completion function.
    $F = switch ($commandAst.CommandElements[0].Value) {
        {$_ -in "awk", "grep", "head", "less", "ls", "sed", "seq", "tail"} {
            "_longopt"
            break
        }
 
        "man" {
            "_man"
            break
        }
 
        "ssh" {
            "_ssh"
            break
        }
 
        Default {
            "_minimal"
            break
        }
    }
 
    # Populate bash programmable completion variables.
    $COMP_LINE = "`"$commandAst`""
    $COMP_WORDS = "('$($commandAst.CommandElements.Extent.Text -join "' '")')" -replace "''", "'"
    for ($i = 1; $i -lt $commandAst.CommandElements.Count; $i++) {
        $extent = $commandAst.CommandElements[$i].Extent
        if ($cursorPosition -lt $extent.EndColumnNumber) {
            # The cursor is in the middle of a word to complete.
            $previousWord = $commandAst.CommandElements[$i - 1].Extent.Text
            $COMP_CWORD = $i
            break
        } elseif ($cursorPosition -eq $extent.EndColumnNumber) {
            # The cursor is immediately after the current word.
            $previousWord = $extent.Text
            $COMP_CWORD = $i + 1
            break
        } elseif ($cursorPosition -lt $extent.StartColumnNumber) {
            # The cursor is within whitespace between the previous and current words.
            $previousWord = $commandAst.CommandElements[$i - 1].Extent.Text
            $COMP_CWORD = $i
            break
        } elseif ($i -eq $commandAst.CommandElements.Count - 1 -and $cursorPosition -gt $extent.EndColumnNumber) {
            # The cursor is within whitespace at the end of the line.
            $previousWord = $extent.Text
            $COMP_CWORD = $i + 1
            break
        }
    }
 
    # Repopulate bash programmable completion variables for scenarios like '/mnt/c/Program Files'/<TAB> where <TAB> should continue completing the quoted path.
    $currentExtent = $commandAst.CommandElements[$COMP_CWORD].Extent
    $previousExtent = $commandAst.CommandElements[$COMP_CWORD - 1].Extent
    if ($currentExtent.Text -like "/*" -and $currentExtent.StartColumnNumber -eq $previousExtent.EndColumnNumber) {
        $COMP_LINE = $COMP_LINE -replace "$($previousExtent.Text)$($currentExtent.Text)", $wordToComplete
        $COMP_WORDS = $COMP_WORDS -replace "$($previousExtent.Text) '$($currentExtent.Text)'", $wordToComplete
        $previousWord = $commandAst.CommandElements[$COMP_CWORD - 2].Extent.Text
        $COMP_CWORD -= 1
    }
 
    # Build the command to pass to WSL.
    $command = $commandAst.CommandElements[0].Value
    $bashCompletion = ". /usr/share/bash-completion/bash_completion 2> /dev/null"
    $commandCompletion = ". /usr/share/bash-completion/completions/$command 2> /dev/null"
    $COMPINPUT = "COMP_LINE=$COMP_LINE; COMP_WORDS=$COMP_WORDS; COMP_CWORD=$COMP_CWORD; COMP_POINT=$cursorPosition"
    $COMPGEN = "bind `"set completion-ignore-case on`" 2> /dev/null; $F `"$command`" `"$wordToComplete`" `"$previousWord`" 2> /dev/null"
    $COMPREPLY = "IFS=`$'n'; echo `"`${COMPREPLY[*]}`""
    $commandLine = "$bashCompletion; $commandCompletion; $COMPINPUT; $COMPGEN; $COMPREPLY" -split ' '
 
    # Invoke bash completion and return CompletionResults.
    $previousCompletionText = ""
    (wsl.exe $commandLine) -split 'n' |
    Sort-Object -Unique -CaseSensitive |
    ForEach-Object {
        if ($wordToComplete -match "(.*=).*") {
            $completionText = Format-WslArgument ($Matches[1] + $_) $true
            $listItemText = $_
        } else {
            $completionText = Format-WslArgument $_ $true
            $listItemText = $completionText
        }
 
        if ($completionText -eq $previousCompletionText) {
            # Differentiate completions that differ only by case otherwise PowerShell will view them as duplicate.
            $listItemText += ' '
        }
 
        $previousCompletionText = $completionText
        [System.Management.Automation.CompletionResult]::new($completionText, $listItemText, 'ParameterName', $completionText)
    }
}
 
# Helper function to escape characters in arguments passed to WSL that would otherwise be misinterpreted.
function global:Format-WslArgument([string]$arg, [bool]$interactive) {
    if ($interactive -and $arg.Contains(" ")) {
        return "'$arg'"
    } else {
        return ($arg -replace " ", " ") -replace "([()|])", ('$1', '`$1')[$interactive]
    }
}

کوډ یو څه ډیر دی پرته له دې چې د باش ځینې داخلي دندو پوه شي ، مګر اساسا هغه څه چې موږ یې کوو دا دي:

  • د لیست په تیریدو سره زموږ د ټولو فنکشن ریپرونو لپاره د دلیل بشپړونکي راجستر کول $commands په پیرامیټر کې -CommandName لپاره Register-ArgumentCompleter.
  • موږ هر کمانډ د شیل فنکشن ته نقشه کوو چې bash د اتوماتیک بشپړتیا لپاره کاروي (د اتوماتیک بشپړتیا مشخصاتو تعریف کولو لپاره ، د باش کارول $Fلپاره لنډیز complete -F <FUNCTION>).
  • د PowerShell دلیلونو بدلول $wordToComplete, $commandAst и $cursorPosition د ځانګړتیاوو سره سم د باش د اتوماتیک بشپړولو دندو لخوا تمه شوي بڼه کې د پروګرام وړ اتوماتیک بشپړول باش
  • موږ د لیږد لپاره د کمانډ لاین ترتیب کوو wsl.exe، کوم چې ډاډ ترلاسه کوي چې چاپیریال په سمه توګه تنظیم شوی ، د مناسب اتومات بشپړولو فنکشن ته زنګ وهي ، او پایلې په کرښه کې په فیشن کې تولیدوي.
  • بیا موږ غږ کوو wsl د کمانډ لاین سره، موږ محصول د لاین جلا کونکو لخوا جلا کوو او د هر یو لپاره تولید کوو CompletionResults، د دوی ترتیب کول او د کرکټرونو څخه تښتیدل لکه ځایونه او قوسونه چې بل ډول به غلط تشریح شي.

د پایلې په توګه، زموږ د لینکس کمانډ شیل به د باش په څیر ورته اتوماتیک بشپړتیا وکاروي! د مثال په ډول:

  • ssh -c <TAB> -J <TAB> -m <TAB> -O <TAB> -o <TAB> -Q <TAB> -w <TAB> -b <TAB>

هر اتوماتیک بشپړتیا د مخکیني دلیل لپاره ځانګړي ارزښتونه وړاندې کوي، د ترتیب کولو ډاټا لوستل لکه د WSL څخه پیژندل شوي کوربه!

<TAB> د پیرامیټونو له لارې تیریږي. <Ctrl + пробел> ټول موجود انتخابونه به ښکاره کړي.

برسیره پردې، له هغه ځایه چې موږ اوس د بش اتوماتیک بشپړتیا لرو، تاسو کولی شئ په مستقیم ډول په PowerShell کې د لینکس لارې اتوماتیک بشپړ کړئ!

  • less /etc/<TAB>
  • ls /usr/share/<TAB>
  • vim ~/.bash<TAB>

په هغه حالتونو کې چې د بش اتوماتیک بشپړتیا کومه پایله نه رامینځته کوي ، پاور شیل د سیسټم ډیفالټ وینډوز لارو ته راستون کیږي. پدې توګه ، په عمل کې ، تاسو کولی شئ په ورته وخت کې ستاسو په اختیار کې دواړه لارې وکاروئ.

پایلې

د PowerShell او WSL په کارولو سره، موږ کولی شو د لینوکس کمانډونه په وینډوز کې د اصلي غوښتنلیکونو په توګه مدغم کړو. د Win32 جوړونو یا لینکس اسانتیاو لټون کولو ته اړتیا نشته یا د لینکس شیل ته په تګ سره ستاسو د کاري جریان مداخله وکړئ. بس WSL نصب کړئترتیب کول PowerShell پروفایل и هغه کمانډونه لیست کړئ چې تاسو یې واردول غواړئ! د لینکس او وینډوز کمانډ پیرامیټرو او فایل لارو لپاره بډایه اتوماتیک فعالیت هغه فعالیت دی چې حتی نن ورځ په اصلي وینډوز کمانډونو کې شتون نلري.

د پورته ذکر شوي بشپړ سرچینې کوډ، او همدارنګه ستاسو د کاري فلو کې د شاملولو لپاره اضافي لارښوونې شتون لري دلته.

کوم لینکس کمانډونه تاسو خورا ګټور ومومئ؟ په وینډوز کې د کار کولو پرمهال کوم نور عام شیان ورک دي؟ په تبصرو کې ولیکئ یا په GitHub کې!

سرچینه: www.habr.com

Add a comment