ื™ื ื˜ืึทื’ืจื™ื™ื˜ื™ื ื’ ืœื™ื ื•ืงืก ืงืึทืžืึทื ื“ื– ืื™ืŸ Windows ื ื™ืฆืŸ PowerShell ืื•ืŸ WSL

ื ื˜ื™ืคึผื™ืฉ ืงืฉื™ื ืคื•ืŸ Windows ื“ืขื•ื•ืขืœืึธืคึผืขืจืก: "ืคืืจื•ื•ืืก ืื™ื– ืขืก ื ืึธืš ื ื™ื˜ <ะ’ะกะขะะ’ะฌะขะ• ะขะฃะข ะ›ะฎะ‘ะ˜ะœะฃะฎ ะšะžะœะะะ”ะฃ LINUX>?. ืฆื™ ืขืก ืื™ื– ืึท ืฉื˜ืึทืจืง ืœืึทืงื›ืขื ืขืŸ less ืึธื“ืขืจ ื‘ืึทืงืึทื ื˜ืข ืžื›ืฉื™ืจื™ื grep ืึธื“ืขืจ sed, Windows ื“ืขื•ื•ืขืœืึธืคึผืขืจืก ื•ื•ื™ืœืŸ ื’ืจื™ื ื’ ืึทืงืกืขืก ืฆื• ื“ื™ ืงืึทืžืึทื ื“ื– ืื™ืŸ ื–ื™ื™ืขืจ ื˜ืขื’ืœืขืš ืึทืจื‘ืขื˜.

Windows ืกื•ื‘ืกื™ืกื˜ืขื ืคึฟืึทืจ ืœื™ื ื•ืงืก (WSL) ื”ืื˜ ื’ืขืžืื›ื˜ ืึท ืจื™ื–ื™ืง ืฉืจื™ื˜ ืคืึธืจื•ื™ืก ืื™ืŸ ื“ืขื ืึทื›ื˜ื•ื ื’. ืขืก ืึทืœืึทื•ื– ืื™ืจ ืฆื• ืจื•ืคืŸ ืœื™ื ื•ืงืก ืงืึทืžืึทื ื“ื– ืคึฟื•ืŸ Windows ื“ื•ืจืš ืคึผืจืึทืงืกื™ื™ื ื’ ื–ื™ื™ wsl.exe (ืœืžืฉืœ wsl ls). ื›ืึธื˜ืฉ ื“ืึธืก ืื™ื– ืึท ื‘ืึทื˜ื™ื™ื˜ื™ืง ืคึฟืึทืจื‘ืขืกืขืจื•ื ื’, ื“ืขื ืึธืคึผืฆื™ืข ืกืึทืคืขืจื– ืคื•ืŸ ืึท ื ื•ืžืขืจ ืคื•ืŸ ื“ื™ืกืึทื“ื•ื•ืึทื ื˜ื™ื“ื–ืฉื™ื–.

  • ืื•ืžืขื˜ื•ื ื“ืขืจืฆื• wsl ื˜ื™ื“ื™ืึทืก ืื•ืŸ ื•ืžื ืึทื˜ื™ืจืœืขืš.
  • Windows ืคึผืึทื˜ืก ืื™ืŸ ืึทืจื’ื•ืžืขื ื˜ืŸ ื˜ืึธืŸ ื ื™ื˜ ืฉื˜ืขื ื“ื™ืง ืึทืจื‘ืขื˜ ื•ื•ื™ื™ึทืœ ื‘ืึทืงืœืึทืฉื™ื– ื–ืขื ืขืŸ ื™ื ื˜ืขืจืคึผืจืึทื˜ืึทื“ ื•ื•ื™ ืึทื ื˜ืœื•ื™ืคืŸ ืื•ืชื™ื•ืช ืืœื ื•ื•ื™ ื•ื•ืขื’ื•ื•ื™ื™ึทื–ืขืจ ืกืขืคึผืขืจื™ื™ื˜ืขืจื–.
  • Windows ืคึผืึทื˜ืก ืื™ืŸ ืึทืจื’ื•ืžืขื ื˜ืŸ ื–ืขื ืขืŸ ื ื™ืฉื˜ ืื™ื‘ืขืจื’ืขื–ืขืฆื˜ ืฆื• ื“ื™ ืงืึธืจืึทืกืคึผืึทื ื“ื™ื ื’ ื‘ืึทืจื’ ืคื•ื ื˜ ืื™ืŸ WSL.
  • ืคืขืœื™ืงื™ื™ึทื˜ ืกืขื˜ื˜ื™ื ื’ืก ื–ืขื ืขืŸ ื ื™ืฉื˜ ืจืขืกืคึผืขืงื˜ืขื“ ืื™ืŸ WSL ืคึผืจืึธื•ืคื™ื™ืœื– ืžื™ื˜ ื™ื™ืœื™ืึทืกื™ื– ืื•ืŸ ืกื•ื•ื™ื•ื•ืข ื•ื•ืขืจื™ืึทื‘ืึทืœื–.
  • ืงืึทืžืคึผืœื™ืฉืึทืŸ ืคื•ืŸ ืœื™ื ื•ืงืก ื“ืจืš ืื™ื– ื ื™ืฉื˜ ื’ืขืฉื˜ื™ืฆื˜.
  • ื‘ืึทืคึฟืขืœืŸ ืงืึทืžืคึผืœื™ืฉืึทืŸ ืื™ื– ื ื™ืฉื˜ ื’ืขืฉื˜ื™ืฆื˜.
  • ืึทืจื’ื•ืžืขื ื˜ ืงืึทืžืคึผืœื™ืฉืึทืŸ ืื™ื– ื ื™ืฉื˜ ื’ืขืฉื˜ื™ืฆื˜.

ื•ื•ื™ ืึท ืจืขื–ื•ืœื˜ืึทื˜, ืœื™ื ื•ืงืก ืงืึทืžืึทื ื“ื– ื–ืขื ืขืŸ ื‘ืื”ืื ื“ืœื˜ ื•ื•ื™ ืฆื•ื•ื™ื™ื˜ ืงืœืึทืก ื‘ื™ืจื’ืขืจืก ืื•ื ื˜ืขืจ Windows - ืื•ืŸ ื–ืขื ืขืŸ ืžืขืจ ืฉื•ื•ืขืจ ืฆื• ื ื•ืฆืŸ ื•ื•ื™ ื’ืขื‘ื•ื™ืจืŸ ืงืึทืžืึทื ื“ื–. ืฆื• ื™ืงื•ื•ืึทืœื™ื™ื– ื–ื™ื™ืขืจ ืจืขื›ื˜, ืขืก ืื™ื– ื ื™ื™ื˜ื™ืง ืฆื• ืกืึธืœื•ื•ืข ื“ื™ ืœื™ืกื˜ืขื“ ืคึผืจืึธื‘ืœืขืžืก.

ืคึผืึธื•ื•ืขืจืฉืขืœืœ ืคื•ื ืงืฆื™ืข ืจืึทืคึผืขืจื–

ืžื™ื˜ PowerShell ืคื•ื ืงืฆื™ืข ืจืึทืคึผืขืจื–, ืžื™ืจ ืงืขื ืขืŸ ืœื™ื™ื’ืŸ ื‘ืึทืคึฟืขืœืŸ ืงืึทืžืคึผืœื™ืฉืึทืŸ ืื•ืŸ ืขืœื™ืžื™ื ื™ืจืŸ ื“ื™ ื ื•ื™ื˜ ืคึฟืึทืจ ืคึผืจืขืคื™ืงืก wsl, ืื™ื‘ืขืจื–ืขืฆืŸ Windows ืคึผืึทื˜ืก ืื™ืŸ WSL ืคึผืึทื˜ืก. ื™ืงืขืจื“ื™ืง ืจืขืงื•ื•ื™ืจืขืžืขื ืฅ ืคึฟืึทืจ ืฉืขืœื–:

  • ืคึฟืึทืจ ื™ืขื“ืขืจ ืœื™ื ื•ืงืก ื‘ืึทืคึฟืขืœ ืขืก ืžื•ื–ืŸ ื–ื™ื™ืŸ ืื™ื™ืŸ ืคื•ื ืงืฆื™ืข ืจืึทืคึผืขืจ ืžื™ื˜ ื“ื™ ื–ืขืœื‘ืข ื ืึธืžืขืŸ.
  • ื“ื™ ืฉืึธืœ ืžื•ื–ืŸ ื“ืขืจืงืขื ืขืŸ ื“ื™ Windows ืคึผืึทื˜ืก ื“ื•ืจื›ื’ืขื’ืื ื’ืขืŸ ื•ื•ื™ ืึทืจื’ื•ืžืขื ื˜ืŸ ืื•ืŸ ื’ืขืจ ื–ื™ื™ ืฆื• 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 (ื“ื•ืจืš ืขืจืฉื˜ืขืจ ืจื™ืžื•ื•ื•ื™ื ื’ ืงื™ื™ืŸ ื™ื™ืœื™ืึทืกื™ื– ื•ื•ืึธืก ื•ื•ืึธืœื˜ ืงืึธื ืคืœื™ืงื˜ ืžื™ื˜ ื“ื™ ืคึฟื•ื ืงืฆื™ืข).

ื“ื™ ืคึฟื•ื ืงืฆื™ืข ื™ื˜ืขืจื™ื™ืฅ ืื™ื‘ืขืจ ื‘ืึทืคึฟืขืœืŸ ืฉื•ืจื” ืึทืจื’ื•ืžืขื ื˜ืŸ, ื“ื™ื˜ืขืจืžืึทื ื– Windows ืคึผืึทื˜ืก ื ื™ืฆืŸ ืงืึทืžืึทื ื“ื– 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, ืึท ื ืึธืจืžืึทืœ ืžืขืงืึทื ื™ื–ืึทื ืคึฟืึทืจ ื“ื™ืคื™ื™ื ื™ื ื’ ืคืขืœื™ืงื™ื™ึทื˜ ืคึผืึทืจืึทืžืขื˜ืขืจืก, ืึธื‘ืขืจ ื‘ืœื•ื™ื– ืคึฟืึทืจ ืงืžื“ืœืขืฅ ืื•ืŸ ืึทื•ื•ืึทื ืกื™ืจื˜ืข ืคืึทื ื’ืงืฉืึทื ื–. ืคื•ืŸ ืงื•ืจืก, ืžื™ืจ ืงืขื ืขืŸ ืžืึทื›ืŸ ืึทื•ื•ืึทื ืกื™ืจื˜ืข ืคืึทื ื’ืงืฉืึทื ื– ืคื•ืŸ ืื•ื ื“ื–ืขืจ ืฉืขืœื–, ืึธื‘ืขืจ ื“ืึธืก ื™ื ื˜ืจืึทื“ื•ืกื™ื– ื•ืžื ื™ื™ื˜ื™ืง ืงืึทืžืคึผืœืึทืงื™ื™ืฉืึทื ื– (ืœืžืฉืœ, 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. ื“ื™ ืคืืœื’ืขื ื“ืข ื•ื•ื™ื™ื–ื˜ ื•ื•ื™ ืฆื• ืœื™ื™ื’ืŸ ื™ื ืกื˜ืจืึทืงืฉืึทื ื– ืฆื• ื“ื™ื™ืŸ PowerShell ืคึผืจืึธืคื™ืœ ืฆื• ืงืึทื ืคื™ื’ื™ืขืจ ืคืขืœื™ืงื™ื™ึทื˜ ืกืขื˜ื˜ื™ื ื’ืก. ืื™ืฆื˜ ืžื™ืจ ืงืขื ืขืŸ ื˜ืึธืŸ ืขืก!

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

ื–ื™ื ื˜ ื“ื™ ืคึผืึทืจืึทืžืขื˜ืขืจืก ื–ืขื ืขืŸ ืžืึธื“ืขืœืขื“ ื ืึธืš $PSDefaultParameterValuesืื™ืจ ืงืขื ืขืŸ ืขืก ืื™ื– ื’ืจื™ื ื’ ืฆื• ื“ื™ืกื™ื™ื‘ืึทืœ ื–ื™ื™ ื˜ืขืžืคึผืขืจืขืจืึทืœื™ ื“ื•ืจืš ื™ื ืกื˜ืึธืœื™ื ื’ ื“ื™ ืฉืœื™ืกืœ "Disabled" ืื™ืŸ ื˜ื™ื™ึทื˜ืฉ $true. ืึทืŸ ื ืึธืš ื ื•ืฅ ืคื•ืŸ ืึท ื‘ืึทื–ื•ื ื“ืขืจ ื”ืึทืฉ ื˜ื™ืฉ ืื™ื– ื“ื™ ืคื™ื™ื™ืงื™ื™ื˜ ืฆื• ื“ื™ืกื™ื™ื‘ืึทืœ $WslDefaultParameterValues ื‘ืึทื–ื•ื ื“ืขืจ ืคื•ืŸ $PSDefaultParameterValues.

ืึทืจื’ื•ืžืขื ื˜ ืงืึทืžืคึผืœื™ืฉืึทืŸ

PowerShell ืึทืœืึทื•ื– ืื™ืจ ืฆื• ืคืึทืจืฉืจื™ื™ึทื‘ืŸ ืึทืจื’ื•ืžืขื ื˜ ื˜ืจื™ื™ืœืขืจื– ืžื™ื˜ ื“ืขื ื‘ืึทืคึฟืขืœ Register-ArgumentCompleter. ื‘ืึทืฉ ื”ืื˜ ืฉื˜ืึทืจืง ืคึผืจืึธื•ื’ืจืึทืžืึทื‘ืึทืœ ืึทื•ื˜ืึธ ืงืึทืžืคึผืœื™ืฉืึทืŸ ืžื›ืฉื™ืจื™ื. WSL ืึทืœืึทื•ื– ืื™ืจ ืฆื• ืจื•ืคืŸ Bash ืคึฟื•ืŸ PowerShell. ืื•ื™ื‘ ืžื™ืจ ืงืขื ืขืŸ ืคืึทืจืฉืจื™ื™ึทื‘ืŸ ืึทืจื’ื•ืžืขื ื˜ ืงืึทืžืคึผืœื™ืฉืึทื ื– ืคึฟืึทืจ ืื•ื ื“ื–ืขืจ PowerShell ืคื•ื ืงืฆื™ืข ืจืึทืคึผืขืจื– ืื•ืŸ ืจื•ืคืŸ ื‘ืึทืฉ ืฆื• ื“ื–ืฉืขื ืขืจื™ื™ื˜ ื“ื™ ืงืึทืžืคึผืœื™ืฉืึทื ื–, ืžื™ืจ ื‘ืึทืงื•ืžืขืŸ ืคื•ืœ ืึทืจื’ื•ืžืขื ื˜ ืงืึทืžืคึผืœื™ืฉืึทืŸ ืžื™ื˜ ื“ืขืจ ื–ืขืœื‘ื™ืงืขืจ ืคึผื™ื ื˜ืœืขื›ืงื™ื™ึทื˜ ื•ื•ื™ ื‘ืึทืฉ ื–ื™ืš!

# 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 ื ื™ืฆื˜ ืคึฟืึทืจ ืึทื•ื˜ืึธืงืึธืžืคึผืœืขื˜ื™ืึธืŸ (ืฆื• ื“ืขืคื™ื ื™ืจืŸ ืึทื•ื˜ืึธืงืึธืžืคึผืœืขื˜ื™ืึธืŸ ืกืคึผืขืกืึทืคืึทืงื™ื™ืฉืึทื ื–, Bash ื ื™ืฆื˜ $F, ืึทื‘ืจื™ื•ื•ื™ื™ื™ืฉืึทืŸ ืคึฟืึทืจ complete -F <FUNCTION>).
  • ืงืึทื ื•ื•ืขืจื˜ื™ื ื’ PowerShell ืึทืจื’ื•ืžืขื ื˜ืŸ $wordToComplete, $commandAst ะธ $cursorPosition ืœื•ื™ื˜ ื“ื™ ืกืคึผืขืกืึทืคืึทืงื™ื™ืฉืึทื ื– ืื™ืŸ ื“ื™ ืคึฟืึธืจืžืึทื˜ ื•ื•ืึธืก ืื™ื– ื’ืขืจื™ื›ื˜ ื“ื•ืจืš ื“ื™ ืึทื•ื˜ืึธืงืึธืžืคึผืœืขื˜ื™ืึธืŸ ืคืึทื ื’ืงืฉืึทื ื– ืคื•ืŸ Bash ืคึผืจืึธื•ื’ืจืึทืžืึทื‘ืึทืœ ืึทื•ื˜ืึธ ืงืึทืžืคึผืœื™ืฉืึทืŸ bash.
  • ืžื™ืจ ืžืึทื›ืŸ ืึท ื‘ืึทืคึฟืขืœ ืฉื•ืจื” ืฆื• ืึทืจื™ื‘ืขืจืคื™ืจืŸ ืฆื• 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 ืจื™ื•ื•ืขืจืฅ ืฆื• ื“ื™ ืกื™ืกื˜ืขื ืคืขืœื™ืงื™ื™ึทื˜ Windows ืคึผืึทื˜ืก. ืื–ื•ื™, ืื™ืŸ ืคื™ืจ, ืื™ืจ ืงืขื ืขืŸ ืกื™ื™ืžืึทืœื˜ื™ื™ื ื™ืึทืกืœื™ ื ื•ืฆืŸ ื‘ื™ื™ื“ืข ืคึผืึทื˜ืก ืœื•ื™ื˜ ื“ื™ื™ืŸ ื“ื™ืกืงืจืขืฉืึทืŸ.

ืกืึธืฃ

ื ื™ืฆืŸ PowerShell ืื•ืŸ WSL, ืžื™ืจ ืงืขื ืขืŸ ื•ื™ืกืฉื˜ื™ืžืขืŸ ืœื™ื ื•ืงืก ืงืึทืžืึทื ื“ื– ืื™ืŸ Windows ื•ื•ื™ ื’ืขื‘ื•ื™ืจืŸ ืึทืคึผืœืึทืงื™ื™ืฉืึทื ื–. ืขืก ืื™ื– ื ื™ื˜ ื“ืึทืจืคึฟืŸ ืฆื• ื–ื•ื›ืŸ ืคึฟืึทืจ Win32 ื‘ื•ื™ืขืŸ ืึธื“ืขืจ ืœื™ื ื•ืงืก ื™ื•ื˜ื™ืœืึทื˜ื™ื– ืึธื“ืขืจ ื™ื‘ืขืจืจื™ื™ึทืกืŸ ื“ื™ื™ืŸ ื•ื•ืึธืจืงืคืœืึธื•ื• ื“ื•ืจืš ื’ื™ื™ืŸ ืฆื• ืึท ืœื™ื ื•ืงืก ืฉืึธืœ. ื ืึธืจ ื™ื ืกื˜ืึทืœื™ืจืŸ WSL, ืงืึทื ืคื™ื’ื™ืขืจ PowerShell ืคึผืจืึธืคื™ืœ ะธ ืจืฉื™ืžื” ื“ื™ ืงืึทืžืึทื ื“ื– ืื™ืจ ื•ื•ื™ืœืŸ ืฆื• ืึทืจื™ื™ึทื ืคื™ืจ! ืจื™ื˜ืฉ ืึทื•ื˜ืึธืงืึธืžืคึผืœืขื˜ื™ืึธืŸ ืคึฟืึทืจ ืœื™ื ื•ืงืก ืื•ืŸ Windows ื‘ืึทืคึฟืขืœืŸ ืคึผืึทืจืึทืžืขื˜ืขืจืก ืื•ืŸ ื˜ืขืงืข ืคึผืึทื˜ืก ืื™ื– ืคืึทื ื’ืงืฉืึทื ืึทืœื™ื˜ื™ ื•ื•ืึธืก ืื™ื– ื ื™ืฉื˜ ืืคื™ืœื• ื‘ื ื™ืžืฆื ืื™ืŸ ื’ืขื‘ื•ื™ืจืŸ Windows ืงืึทืžืึทื ื“ื– ื”ื™ื™ึทื ื˜.

ื“ื™ ืคื•ืœ ืžืงื•ืจ ืงืึธื“ ื“ื™ืกืงืจื™ื™ื‘ื“ ืื•ื™ื‘ืŸ, ื•ื•ื™ ื’ืขื–ื•ื ื˜ ื•ื•ื™ ื ืึธืš ื’ื™ื™ื“ืœื™ื™ื ื– ืคึฟืึทืจ ื™ื ืงืึธืจืคึผืขืจื™ื™ื˜ื™ื ื’ ืขืก ืื™ืŸ ื“ื™ื™ืŸ ื•ื•ืึธืจืงืคืœืึธื•ื•, ืื™ื– ื‘ื ื™ืžืฆื ื“ืึธ.

ื•ื•ืึธืก ืœื™ื ื•ืงืก ืงืึทืžืึทื ื“ื– ื˜ืึธืŸ ืื™ืจ ื’ืขืคึฟื™ื ืขืŸ ืจื•ื‘ึฟ ื ื•ืฆื™ืง? ื•ื•ืึธืก ืื ื“ืขืจืข ืคึผืจืึธืกื˜ ื˜ื™ื ื’ื– ืคืขืœื ื“ื™ืง ื•ื•ืขืŸ ืื™ืจ ืึทืจื‘ืขื˜ ืื™ืŸ Windows? ืฉืจื™ื™ื‘ ืื™ืŸ ื“ื™ ื‘ืึทืžืขืจืงื•ื ื’ืขืŸ ืึธื“ืขืจ ืื•ื™ืฃ GitHub!

ืžืงื•ืจ: www.habr.com

ืœื™ื™ื’ืŸ ืึท ื‘ืึทืžืขืจืงื•ื ื’