💻

【0からのWindows環境構築】Powershellの操作をできるだけLinux/Macの操作感に近づける (Linuxコマンド導入+α)

2024/03/18に公開

はじめに

こんにちは。普段はSaaS企業でWebアプリケーションエンジニアをしているkeemicroです。
業務ではWindows、プライベートではWindows上のLinux仮想マシン等を使用してプログラミング等をしているのですが、その際気になるのがスイッチングコストです。
自分としては、自分が操作をしやすいと感じるLinux側に操作を合わせたいと考えており、業務のWindowsにLinuxコマンド(uutils/coreutils)をインストールし、かつbash風キーバインドにして使用しています。

業務の新人研修等、たまに自分の環境構築方法を人に教える機会があり、その際、参照できる再現性のある環境構築ドキュメントが欲しいと思い、まとめるにいたりました。
環境にユーザーが何もプリインストールしていない状態を想定して、今回は自分が普段使用しているbash風のキーバインドかつLinuxコマンド(の大部分)が使えるPowerShellの環境を0から構築していこうと思います。

今回紹介するuutils/coreutils等を用いたキーバインドの変更等は既に何人もの先駆者の方が紹介している[1][2]やり方ではあるので、そちらを見た方がわかりやすく早いかと思うのですが、自分が構築しやすい手順で、自分なりにまとめた次第です🙏
よろしくお願いします。

環境

  • Windows 10

この記事で説明すること・しないこと

  • 説明すること

    • まっさらな状態のWindowsとPowerShellのコンソール環境を、Linux/Mac風のコンソール環境にする方法
    • Powershellで使える便利な機能の紹介
  • 説明しないこと

    • PowerShellの見た目をおしゃれにするテーマ設定・カスタマイズ

準備

今回は0からの環境構築をテーマにしているので、VSCodeやScoopなど、編集に必要なツールの導入も行っていきます。
やってることは結局以下です。

  • パッケージマネージャのインストール
  • (scoopで使うための)gitのインストール
  • PowerShell編集用にVSCodeのインストール
  • PowerShell 7のインストール

既に使っているエディタやパッケージマネージャ(Chocolatey, winget等)がある方はVSCodeやScoopのインストールは読み飛ばしてしまって大丈夫です。
その場合、この項以降のscoopやVSCodeでやってる部分は各種ツールでの操作で置き換えて読んでください。

Scoopのインストール

ScoopはWindowsで使えるコマンドラインインストーラ、いわゆるパッケージマネージャです。
Scoopをインストールすることで、コマンドラインからWindowsの各種パッケージをインストール、管理することができます。

インストーラを実行するのに必要な権限をWindows Powershellに与えます。

$ Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

以下コマンドでインストールすることができます

$ iwr -useb get.scoop.sh | iex

確認

$ scoop --help

(必要であれば)gitのインストール
Scoopは内部でgitを使用するため、gitのインストールがまだな場合はインストールをします。

$ scoop install git

VSCodeのインストール

Powershellのプロファイル編集用にVSCodeのインストールを行います。
既にインストールしていたり、別のエディタで編集する場合は飛ばして良いです。

$ scoop bucket add extras

VSCodeのインストール

$ scoop install vscode

PowerShell 7のインストール

もし今使っているPowerShellのバージョンが7.xより下のバージョンの場合は、Powershellの7.x系をScoopでインストールしましょう。

PowerShell 7は既存のWindows Powershellとのモジュールの互換性を持ち、かつ使える機能も多いです。
基本Windows Powershellでできて、Powershell 7でできないことはないので後者を使っていきましょう。

サードパーティバケットの追加

$ scoop bucket add dorado https://github.com/chawyehsu/dorado

Scoopで最新のPowershellをインストールします。

$ scoop install powershell

Windowsの検索バーでPowerShellと打った際、新しくPowerShell 7 という名前のアプリが表示されるようになったと思います。Windows Powershellを閉じて、ここからはPowerShell 7を開いて作業していきます。

参考
PowerShell 7について詳しくは以下
https://learn.microsoft.com/ja-jp/powershell/scripting/whats-new/migrating-from-windows-powershell-51-to-powershell-7?view=powershell-7.4

Powershellのプロファイルを作成する

プロファイルは、PowerShell起動時に読み込まれるスクリプトです。
ここにPowerShellの設定を記述していくので、これをまず作成します。

また、必要なときに以下を適宜行います。

  • 設定ファイルのパスの確認
    • Powershell上で$PROFILEと打つと表示される
  • 設定ファイルの手動での再読み込み
    • . $PROFILE

VSCodeでプロファイルを作成、編集する場合、以下コマンドで設定ファイルを開きます。

$ code $PROFILE

これで、まっさらな状態のMicrosoft.PowerShell_profile.ps1というファイルが開かれると思います。

これがプロファイルにあたるため、これを編集していきます。

Linux/Macにコマンドとキーバインドを近づける

ここからは各種OSSとエイリアスの設定、Powershellのキーバインドの設定を行い、Linux風のキーバインドに近づけていきます。

Rust製Linux代替コマンドのインストール・エイリアス設定

■ coreutilsのインストール
https://github.com/uutils/coreutils/
uutils/coreutilsはLinux/UNIX系のOSで使用されるcat、ls、rmなどの、核となるコマンドラインツール郡をRustにより再実装したものです。
uutils/coreutilsはクロスプラットフォーム対応であるため、Windowsでも使えます。
uutils/coreutilsが提供している各種コマンドに対してPowerShell側でエイリアスを貼り、Linux/Macと同様の機能を持つcatやlsコマンドを使用可能にします。

$ scoop install uutils-coreutils

コマンドの有効化
PowerShellのプロファイルを開いて、以下を追加

$PROFILE
@"
  arch, base32, base64, basename, cat, cksum, comm, cp, cut, date, df, dircolors, dirname,
  echo, env, expand, expr, factor, false, fmt, fold, hashsum, head, hostname, join, link, ln, ls,
  md5sum, mkdir, mktemp, more, mv, nl, nproc, od, paste, printenv, printf, ptx, pwd,
  readlink, realpath, relpath, rm, rmdir, seq, sha1sum, sha224sum, sha256sum, sha3-224sum,
  sha3-256sum, sha3-384sum, sha3-512sum, sha384sum, sha3sum, sha512sum, shake128sum,
  shake256sum, shred, shuf, sleep, sort, split, sum, sync, tac, tail, tee, test, touch, tr,
  true, truncate, tsort, unexpand, uniq, wc, whoami, yes
"@ -split ',' |
ForEach-Object { $_.trim() } |
Where-Object { ! @('tee', 'sort', 'sleep').Contains($_) } |
ForEach-Object {
    $cmd = $_
    if (Test-Path Alias:$cmd) { Remove-Item -Path Alias:$cmd }
    $fn = '$input | uutils ' + $cmd + ' $args'
    Invoke-Expression "function global:$cmd { $fn }" 
}

上記は先駆者様のコードとインストール方法を参考させていただいております。

これで、エイリアス設定したLinuxコマンドについては、以下のように使えるようになりました。

$ echo hogehoge >> test.txt
$ echo fugafuga >> test.txt

$ cat test.txt 
hogehoge
fugafuga

uutils/coreutilsで対応しているコマンドのリストは公式ドキュメントに記載があります。上記に加え、必要ならば追加しましょう。

その他、uutils/coreutilsで対応していないコマンドについては、自分は以下のように設定しています。

■ grep

・ripgrepのインストール
https://github.com/BurntSushi/ripgrep

$ scoop install ripgrep

・エイリアスを設定

$PROFILE
Set-Alias grep rg

■ which

$PROFILE
Set-Alias which where.exe

■ history

$PROFILE
function history() {
  if ($args.Length -eq 0){
      cat -n (Get-PSReadlineOption).HistorySavePath | tail -n 1000
  } elseif ($args.Length -ne 0){
    cat -n (Get-PSReadlineOption).HistorySavePath | tail -n $args
  }
}

bash風キーバインドの設定

bash風のキーバインドを使えるようにします。
PowerShellのプロファイルを開いて、以下を追加します。

これにより、Ctrl + Aによる行頭への移動やCtrl + Wによる単語の削除等が可能になります。

$PROFILE
Set-PSReadLineOption -EditMode Emacs

また、上記だけではCtrl + 矢印キーにおける単語間の移動に対応していないので、以下も追加します。

$PROFILE
# Ctrl  矢印キーによる単語移動
Set-PSReadLineKeyHandler -Chord Ctrl+RightArrow -Function ForwardWord
Set-PSReadLineKeyHandler -Chord Ctrl+LeftArrow -Function BackwardWord

PowerShellで設定されているキーバインドの一覧は以下で参照できるので、適宜ご参照ください。

Get-PSReadlineKeyHandler 

その他

自分は以下を追加で設定しています。

zsh風のtab補完

$PROFILE
Set-PSReadLineKeyHandler -Key Tab -Function MenuComplete

PSFzfによるfuzzy searchの設定

https://github.com/kelleyma49/PSFzf

  • Ctrl + G

    • 現在ディレクトリ以下のパスをfuzzy search
  • Ctrl + R

    • これまで打ったコマンドのfuzzy search

scoopでPSFzf、fzfをインストールし、

 scoop install PSFzf
 scoop install fzf

$PROFILEに以下を記述することで利用可能です。

$PROFILE
Set-PsFzfOption -PSReadlineChordProvider 'Ctrl+g' -PSReadlineChordReverseHistory 'Ctrl+r'

便利設定

ここからはおまけで、自分がPowerShellを使っていて便利だな、と感じた機能やコマンドについて紹介していきます。

予測IntelliSenseによるコマンド補完

https://learn.microsoft.com/ja-jp/powershell/scripting/learn/shell/using-predictors?view=powershell-7.4
PowerShellには予測IntelliSenseという機能があります。
この設定を有効にすると、それまでに打ったコマンドの履歴に基づいて、コンソール上にコマンドの候補が表示されます。

現在、予測IntelliSenseは2つのスタイルを提供しており、それぞれ、インライン表示、リスト表示に対応しています。


インライン表示設定の予測IntelliSense


リスト表示設定の予測IntelliSense

リスト表示の予測IntelliSenseは、結果的には先程紹介したCtrl+Rによるfuzzy searchと同等のことをしているのですが、コマンドを打たずにコマンド履歴をリスト表示するので自分としてはより直感的に使えると感じ、こちらをよく使っています。

PSReadLineモジュールを最新にアップデートし、

Install-Module -Name PSReadLine -AllowPrerelease -Force

プロファイルに以下を記述することで利用可能です。

$PROFILE
Set-PSReadLineOption -PredictionSource History
Set-PSReadLineOption -PredictionViewStyle ListView
# or
# Set-PSReadLineOption -PredictionViewStyle InlineView

zoxideによるディレクトリ移動

https://github.com/ajeetdsouza/zoxide
zoxideはCUIでのディレクトリ移動を便利にするコマンドラインツールです。
インストールすることで、以下のようなコマンドが使えるようになります。

  • z
    • 指定したパスに最も一致するパスに移動する
  • zi
    • zのインタラクティブなバージョン。指定したパスにあいまい一致する候補のリストがCUI上に表示され、その中から選択したディレクトリに移動できます。

動作イメージ

ここでやっているのは

  1. cdで深いフォルダ階層に移動(.\some\long\path)
  2. z someでsomeに移動
  3. ziでインタラクティブに元のディレクトリに移動

zoxideを使うことで、CUI上でのディレクトリ移動を快適にできます。

インストール・設定

■ zoxideのインストール

$ scoop install zoxide

■ zoxide用の関数の定義とエイリアスをプロファイルに追加
以下をプロファイルに追加することで、z, ziがそれぞれコマンドとして使えるようになります。

$PROFILE
Invoke-Expression (& {
    $hook = if ($PSVersionTable.PSVersion.Major -lt 6) { 'prompt' } else { 'pwd' }
    (zoxide init --hook $hook powershell) -join "`n"
})

PowerShell上でGitのステータスを表示する

https://github.com/dahlbyk/posh-git#using-posh-git

Git Bashのように、PowerShell上にGitのステータスの表示を可能にします。

以下二つのコマンドを実行します。

Install-Module posh-git -Scope CurrentUser -Force
Add-PoshGitToProfile

これで、Powershellの画面上にGitのステータスが表示されるようになりました。

コード全体

ここまでに$PROFILEに書いたコード全体は以下になります。

終わりに

今回の設定で、自分にとってスイッチングコストを意識せずに済む程度には、PowerShellの動作をMac/Linuxの操作性に近づけることができました。
Windowsでは仮想マシン上のLinux環境やWSLを使って開発を行う方が、普段Linuxコマンドに慣れ親しんだ自分としては開発しやすいと感じるのですが、自分のような背景のユーザーが業務上の都合でWindowsのPowershellを触る必要がある場合、そのコンソール操作をストレスレスにできるのは大きなメリットだと感じています。

今回紹介したuutils/coreutilsのような、クロスプラットフォームで動作するRust製のLinuxコマンドはOSSとして開発がされているものも多くあります。今回対応していないコマンド郡などについては、そういったものを探して取り入れてみるのも良いと思います。

皆さんも独自のカスタマイズを行い、PowerShell環境を快適にしていきましょう。

参考

脚注
  1. https://secon.dev/entry/2020/08/17/070735/ ↩︎

  2. https://blog.mamansoft.net/2020/05/31/windows-terminal-and-power-shell-makes-beautiful/ ↩︎

Discussion