ืฉืืื ืืืคืืกืืช ืืืคืชืื Windows: "ืืื ืขืืืื ืืื <ะะกะขะะะฌะขะ ะขะฃะข ะะฎะะะะฃะฎ ะะะะะะะฃ LINUX>
?. ืืื ืื ืืืืืจ ืืืืืงื ืืืงื less
ืื ืืืื ืืืืจืื grep
ืื sed
, ืืคืชืื Windows ืจืืฆืื ืืืฉื ื ืืื ืืคืงืืืืช ืืื ืืขืืืื ืืืืืืืืืช ืฉืืื.
wsl.exe
(ืืืืื: wsl ls
). ืืืจืืช ืฉืืืืืจ ืืฉืืคืืจ ืืฉืืขืืชื, ืืคืฉืจืืช ืื ืกืืืืช ืืืกืคืจ ืืกืจืื ืืช.
- ืชืืกืคืช ืืื ืืงืื
wsl
ืืืืืข ืืื ืืืขื. - ื ืชืืื Windows ืืืจืืืื ืืื ืื ืชืืื ืขืืืืื ืืืืืื ืฉืืืืืกื ืื ืืืืืจืืื ืืชืคืจืฉืื ืืชืืื ืืจืืื ืืื ืืืคืจืืื ืกืคืจืืืช.
- ื ืชืืื Windows ืืืจืืืื ืืื ืืื ื ืืชืืจืืืื ืื ืงืืืช ืืืขืื ื ืืืชืืืื ื-WSL.
- ืืืืจืืช ืืจืืจืช ืืืืื ืืื ื ืืืืืืืช ืืคืจืืคืืื WSL ืขื ืืื ืืืื ืืืฉืชื ื ืกืืืื.
- ืืฉืืืช ื ืชืื ืืื ืืงืก ืืื ื ื ืชืืืช.
- ืืฉืืืช ืคืงืืื ืืื ื ื ืชืืืช.
- ืืฉืืืช ืืืขืื ืื ืืื ื ื ืชืืืช.
ืืชืืฆืื ืืื, ืคืงืืืืช ืืื ืืงืก ืืืืคืืืช ืืื ืืืจืืื ืกืื ื' ืชืืช Windows - ืืื ืงืฉืืช ืืืชืจ ืืฉืืืืฉ ืืืฉืจ ืคืงืืืืช ืืงืืจืืืช. ืืื ืืืฉืืืช ืืช ืืืืืืชืืื, ืืฉ ืฆืืจื ืืคืชืืจ ืืช ืืืขืืืช ืืืคืืจืืืช.
ืขืืืคืืช ืคืื ืงืฆืืืช ืฉื PowerShell
ืขื ืขืืืคืืช ืคืื ืงืฆืืืช ืฉื PowerShell, ืื ื ืืืืืื ืืืืกืืฃ ืืฉืืืช ืคืงืืืืช ืืืืื ืืช ืืฆืืจื ืืงืืืืืืช wsl
, ืชืจืืื ื ืชืืื Windows ืื ืชืืื WSL. ืืจืืฉืืช ืืกืืกืืืช ืืงืื ืืืืช:
- ืขืืืจ ืื ืคืงืืืช ืืื ืืงืก ืืืืืช ืืืืืช ืืขืืคืช ืคืื ืงืฆืื ืืืช ืขื ืืืชื ืฉื.
- ืืืขืืคืช ืืืืืช ืืืืืช ืืช ื ืชืืื Windows ืฉืืืขืืจื ืืืจืืืื ืืื ืืืืืืจ ืืืชื ืื ืชืืื WSL.
- ืืงืืืคื ืฆืจืืื ืืืชืงืฉืจ
wsl
ืขื ืคืงืืืช Linux ืืืชืืืื ืืื ืงืื ืฆืื ืืจ ืืืขืืจืช ืื ืืจืืืื ืืื ืฉื ืฉืืจืช ืืคืงืืื ืืืืขืืจืื ืืคืื ืงืฆืื.
ืืืืืื ืฉื ืืชื ืืืืื ืืช ืืชืื ืืช ืืื ืขื ืื ืคืงืืื, ืื ื ืืืืืื ืืคืฉื ืืช ืืืืืจื ืฉื ืขืืืคืืช ืืื ืืืืฆืืจ ืืืชื ืืืืคื ืืื ืื ืืชืื ืจืฉืืื ืฉื ืคืงืืืืช ืืืืืื.
# 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
ืงืืืฆืช ืืคืงืืืืช ืืืกืืกืืช ืืืฆืืช ืืื, ืืื ืืชื ืืืื ืืืฆืืจ ืืขืืคืช ืขืืืจ ืื ืคืงืืืช ืืื ืืงืก ืขื ืืื ืืืกืคืชื ืืจืฉืืื. ืื ืชืืกืืฃ ืืช ืืงืื ืืื ืืฉืื
ืืืืจืืช ืืจืืจืช ืืืื
ืืืื ืืงืก, ืืงืืื ืืืืืืจ ืืื ืืืื ื/ืื ืืฉืชื ื ืกืืืื ืืคืจืืคืืื ืืชืืืจืืช, ืืืืจืช ืคืจืืืจื ืืจืืจืช ืืืื ืขืืืจ ืคืงืืืืช ืืฉืืืืฉ ืชืืืฃ (ืืืืืื, alias ls=ls -AFh
ืื export LESS=-i
). ืืื ืืืกืจืื ืืช ืฉื ืคืจืืงืกื ืืจื ืืขืืคืช ืื ืืื ืืจืืงืืืืืช wsl.exe
- ืฉืืคืจืืคืืืื ืืื ื ื ืืขื ืื, ืืืื ืืคืฉืจืืืืช ืืื ืืื ื ืืืื ืืช ืืืจืืจืช ืืืื (ืืืืืจ. ls
ื-WSL ื wsl ls
ืืชื ืื ืืืจืช ืขื ืืืื ืื ืฉืืืืืจ ืืขืื).
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
. ืืชืจืื ื ืืกืฃ ืฉื ืืืืช hash ื ืคืจืืช ืืื ืืืืืืช ืืืฉืืืช $WslDefaultParameterValues
ืื ืคืจื ื $PSDefaultParameterValues
.
ืืฉืืืช ืืืขืื
PowerShell ืืืคืฉืจ ืื ืืจืฉืื ืืจืืืืจืื ืฉื ืืจืืืื ืืื ืืืืฆืขืืช ืืคืงืืื Register-ArgumentCompleter
. ืืืฉ ืืฉ ืขืืฆืื
# 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]
}
}
ืืงืื ืืขื ืฆืคืืฃ ืืืื ืืืืื ืืืง ืืืคืื ืงืฆืืืช ืืคื ืืืืืช ืฉื bash, ืืื ืืขืฆื ืื ืฉืื ืื ื ืขืืฉืื ืื:
- ืจืืฉืื ืืฉืืื ืืจืืืื ืืื ืขืืืจ ืื ืขืืืคืืช ืืคืื ืงืฆืืืช ืฉืื ื ืขื ืืื ืืขืืจืช ืจืฉืืื
$commands
ืืคืจืืืจ-CommandName
ืขืืืจRegister-ArgumentCompleter
. - ืื ื ืืืคืื ืื ืคืงืืื ืืคืื ืงืฆืืืช ืืืขืืคืช ืฉืื ืืฉืชืืฉืช bash ืืืฉืืื ืืืืืืืืช (ืืื ืืืืืืจ ืืคืจืื ืืฉืืื ืืืืืืืืช, bash ืืฉืชืืฉืช
$F
, ืงืืฆืืจ ืฉืcomplete -F <FUNCTION>
). - ืืืจืช ืืจืืืื ืืื ืฉื PowerShell
$wordToComplete
,$commandAst
ะธ$cursorPosition
ืืคืืจืื ืืืฆืืคื ืืคืื ืงืฆืืืช ืืืฉืืื ืืืืืืืืืช ืฉื bash ืืืชืื ืืืคืจืืืืืฉืืื ืืืืืืืืช ืื ืืชื ืช ืืชืื ืืช ืึทืึฒืืึนื. - ืื ื ืืจืืืืื ืฉืืจืช ืคืงืืื ืืืขืืจื
wsl.exe
, ืืืืืื ืฉืืกืืืื ืืืืืจืช ืืืืื, ืงืืจื ืืคืื ืงืฆืืืช ืืืฉืืื ืืืืืืืืืช ืืืชืืืื, ืืืืฆืื ืืช ืืชืืฆืืืช ืืฉืืจื ืืืจ ืฉืืจื. - ืืื ืื ืื ื ืืชืงืฉืจืื
wsl
ืขื ืฉืืจืช ืืคืงืืื, ืื ื ืืคืจืืืื ืืช ืืคืื ืืคื ืืคืจืืื ืฉืืจืืช ืืืืืฆืจืื ืขืืืจ ืื ืืื ืืืCompletionResults
, ืืืื ืฉืืื ืืืืืืืืช ืชืืืื ืืืื ืจืืืืื ืืกืืืจืืื ืฉืืืจืช ืืื ืืชืคืจืฉืื ืื ื ืืื.
ืืชืืฆืื ืืื, ืืขืืคืืช ืืคืงืืืืช ืฉื ืืื ืืงืก ืฉืื ื ืืฉืชืืฉื ืืืืืง ืืืืชื ืืฉืืื ืืืืืืืืช ืืื bash! ืืืืืื:
ssh -c <TAB> -J <TAB> -m <TAB> -O <TAB> -o <TAB> -Q <TAB> -w <TAB> -b <TAB>
ืื ืืฉืืื ืืืืืืืืช ืืกืคืงืช ืขืจืืื ืกืคืฆืืคืืื ืืืจืืืื ื ืืงืืื, ืืงืืจืืช ื ืชืื ื ืชืฆืืจื ืืืื ืืืจืืื ืืืืขืื ื-WSL!
<TAB>
ืืขืืืจ ืขื ืืคืจืืืจืื. <Ctrl + ะฟัะพะฑะตะป>
ืืฆืื ืืช ืื ืืืคืฉืจืืืืช ืืืืื ืืช.
ืื ืืกืฃ, ืืืืืื ืฉืืฉ ืื ื ืืขืช ืืฉืืื ืืืืืืืืช ืฉื bash, ืืชื ืืืื ืืืฉืืื ืืืืืืืืช ื ืชืืื ืืื ืืงืก ืืฉืืจืืช ื-PowerShell!
less /etc/<TAB>
ls /usr/share/<TAB>
vim ~/.bash<TAB>
ืืืงืจืื ืืื ืืฉืืื ืืืืืืืืช ืฉื bash ืืื ื ืื ืืื ืชืืฆืืืช, PowerShell ืืืืจ ืื ืชืืื ืืจืืจืช ืืืืื ืฉื Windows. ืื, ืืคืืขื, ืืชื ืืืื ืืืฉืชืืฉ ืืฉื ื ืื ืชืืืื ืื ืืื ืืช ืืคื ืฉืืงืื ืืขืชื.
ืืกืงื ื
ืืืืฆืขืืช PowerShell ื-WSL, ืื ื ืืืืืื ืืฉืื ืคืงืืืืช ืืื ืืงืก ื-Windows ืืืืฉืืืื ืืงืืจืืื. ืืื ืฆืืจื ืืืคืฉ ืื ืืืช Win32 ืื ืืื ืขืืจ ืฉื ืืื ืืงืก ืื ืืืคืจืืข ืืืจืืืช ืืขืืืื ืฉืื ืขื ืืื ืืขืืจ ืืืขืืคืช ืืื ืืงืก. ืจึทืง
ืงืื ืืืงืืจ ืืืื ืืืชืืืจ ืืขืื, ืืื ืื ืื ืืืืช ื ืืกืคืืช ืืฉืืืืื ืืืจืืืช ืืขืืืื ืฉืื, ืืืื
ืืืื ืคืงืืืืช Linux ืืื ืฉืืืืฉืืืช ืืขืื ืื? ืืืื ืืืจืื ื ืคืืฆืื ื ืืกืคืื ืืกืจืื ืืขืืืื ื-Windows? ืืชืื ืืชืืืืืช ืื
ืืงืืจ: www.habr.com