PowerShellで lsコマンド  を使い易くする（簡単）

# PowerShellで lsコマンド を改造して、使いやすい lslコマンド を作成する

Shell でディレクトリの中身を確認する為に ls って良く使いますよね。
左右の薬指で瞬時に実行できる素晴らしいコマンドですが、これをPowerShellで使用していて少々使い難い面があったので、ファンクションで使い易い ls を作ることにしました。

具体的には次の２つの機能を追加します。
① ls からファイルを開けるようにする　
② ls からフォルダーを移動出来るようにする　

## 
では一先ず PowerShell で ls を実行してみます。

```ruby:PowerShell
> ls

    Directory: D:\Shits\HFprojects\ActionRoom

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----          2025/03/20    13:07                .vscode
d----          2025/03/20    13:07                assets
d----          2025/03/20    13:07                dump
d----          2025/03/20    13:07                export
d----          2025/03/20    13:07                source
-a---          2024/04/14    21:02            240 hxformat.json
-a---          2025/01/06    22:48           3386 Project.xml

```

ここでファイルを発見してめでたしめでたし。表示されたファイル名をコピペして "Invoke-Item" 略して "ii" を実行すればすぐ開くのですが、もっと良い方法がありそうだと思いませんか？という事でやってみます。
あまり時間の短縮にはならないかもですが、改造って楽しいですよね👍

### 1. Get-ChildItem の要素を取り出して表示させる
"ls" は PowerShell で言うところの "Get-ChildItem" なので、これを使用して考えてみます。

始めに、ls に必要な要素を取得してみます。
先程 ls を実行した際、表示された要素は "Directory", "Mode", "LastWriteTime", "Length", "Name" の5つでした。これを要素別に代入出来るか検証します。
```ruby:PowerShell
# ① Directory
> $current_dir = Get-Location
> Write-Host "ディレクトリ：" -NoNewLine; Write-Host $currentDir
# 実行すると次の様に表示されます（現在のディレクトリpathです）
ディレクトリ：D:\Shits\HFprojects\ActionRoom

# ② Mode （一旦１つだけ要素を取得してみます）
> $child_items = Get-ChildItem
> $mode = [string]$child_items[0].Mode
> Write-Host $mode
# 実行すると次の様に表示されます（現在のディレクトリ下にある1つめの要素のMode）
d----

# ③ LastWriteTime
> $last = [string]$child_items[0].LastWriteTime
> Write-Host $last_write
# 実行すると次の様に表示されます（現在のディレクトリ下にある1つめの要素のLastWriteTime）
03/20/2025 13:07:16

# ④ Length
> $len = [string]$child_items[0].Length
> Write-Host $length
# 実行すると次の様に表示されます（現在のディレクトリ下にある1つめの要素のLength）
1

# Name
> $name = [string]$child_items[0].Name
> Write-Host $name
# 実行すると次の様に表示されます（現在のディレクトリ下にある1つめの要素のName）
.vscode

```

これで各要素の取得テストが出来たので、一旦変数を消します。
```ruby:PowerShell
> $current_dir = $child_items = $mode = $last = $len = $name = $null
> [GC]::Collect()
```

### 2. "ls" のレイアウトを整える
ここまでで要素取得の準備が完了しました。
では、ファンクションを作成する為に VScode で PowerShell のプロファイルを開きます。
（別に notepad でも vim でも何でもいいですけど。）
```ruby:PowerShell
> code $profile
```

まず、プロファイルにレイアウトを変更した "ls" のファンクションを作成します。入力スピードを重視して名前は "lsl" です。

:::note info
コマンド ls 自体 を改造版に変更したい場合は、Set-Alias で出来ますが、今回は残す方向で進めます。
:::

```ruby:Microsoft.PowerShell_profile.ps1
function lsl{
    # Get-Location と Get-ChildItem の実行結果を変数に代入
    $current_dir = Get-Location
    $child_items = Get-ChildItem
    
    # ls 同様、ヘッダーを現在のディレクトリpathにします
    Write-Host ""
    Write-Host "ディレクトリ：" -NoNewLine; Write-Host $current_dir
    Write-Host ""
    
    # 見出し行の表示
    Write-Host "Mode    " -NoNewLine; 
    Write-Host "LastWriteTime       " -NoNewLine; 
    Write-Host " Length     " -NoNewLine;
    Write-Host "Name"
    Write-Host "------  " -NoNewLine; 
    Write-Host "-------------------" -NoNewLine; 
    Write-Host "  ---------" -NoNewLine; 
    Write-Host "  ------------------------------"
    
    # 配列$child_itemsの各要素を１行ずつ表示
    foreach($i in $child_items){
        $mode = [string]$i.Mode
        $last = [string]$i.LastWriteTime
        # 検証でディレクトリの Length は １ だったので、非表示に変更します
        $len = [string]$i.Length -eq "1"? "":[string]$i.Length
        $name = [string]$i.Name
        Write-Host $mode.PadRight(8,' ') -NoNewLine; 
        Write-Host $last.PadRight(20,' ') -NoNewLine; 
        Write-Host $len.PadLeft(10,' ') -NoNewLine;
        Write-Host "  " -NoNewLine; 
        Write-Host $name
    } 
    Write-Host ""
    
    # 変数の解放
    $current_dir = $child_items = $mode = $last = $len = $name = $null
    [GC]::Collect()
}

```

:::note warn
2025.5.22追記

ディレクトリのLength( 変数 $len )を取るのにラムダ式を使ったのですが、どうやらPowerShell5ではエラーとなる様です（筆者は7を使っています）。

5の場合は、
```
$len = [string]$i.Length -eq "1"? "":[string]$i.Length
```
ではなく普通のif文として、
```
if([string]$i.Length -eq "1"){
    $len = ""
}else{
    $len = [string]$i.Length
}
```
に変更すれば動くと思います。
:::

Microsoft.PowerShell_profile.ps1 ファイルを保存して閉じます。
ファンクションを使用出来る様にする為、PowerShell でプロファイルを更新します。

```ruby:PowerShell
> . $profile
```

実行
```ruby:PowerShell
> lsl

ディレクトリ：D:\Shits\HFprojects\ActionRoom

Mode    LastWriteTime        Length     Name
------  -------------------  ---------  ------------------------------
d----   03/20/2025 13:07:16             .vscode
d----   03/20/2025 13:07:16             assets
d----   03/20/2025 13:07:16             dump
d----   03/20/2025 13:07:17             export
d----   03/20/2025 13:07:22             source
-a---   04/14/2024 21:02:09        240  hxformat.json
-a---   01/06/2025 22:48:56       3386  Project.xml

```
各要素が綺麗に整列しました。次は機能の追加です。

### 3. "ls" に機能を追加する

ls（lslですが...）から　ファイルを開く/ディレクトリを移動する　ために次の簡単な処理を追加します。
・行番号を追加
・行番号を指定してファイルを開く
・行番号を指定してディレクトリを移動する

では機能を追加するために Microsoft.PowerShell_profile.ps1 に戻り、以下コメントの箇所を編集（追記）します。

```ruby:Microsoft.PowerShell_profile.ps1
function lsl{
    $current_dir = Get-Location
    $child_items = Get-ChildItem
    
    Write-Host ""
    Write-Host "ディレクトリ：" -NoNewLine; Write-Host $current_dir
    Write-Host ""

    # Num という見出しを追加
    Write-Host "Num    " -NoNewLine;
    
    Write-Host "Mode    " -NoNewLine; 
    Write-Host "LastWriteTime       " -NoNewLine; 
    Write-Host " Length     " -NoNewLine;
    Write-Host "Name"
    
    # Num の水平線を追加
    Write-Host "-----  " -NoNewLine;
    
    Write-Host "------  " -NoNewLine; 
    Write-Host "-------------------" -NoNewLine; 
    Write-Host "  ---------" -NoNewLine; 
    Write-Host "  ------------------------------"

    # 変数 $a に 1 を代入
    $a = 1
    
    foreach($i in $child_items){

        # 変数 $num に 型変換した $a を代入
        $num = [string]$a

        $mode = [string]$i.Mode
        $last = [string]$i.LastWriteTime
        $len = [string]$i.Length -eq "1"? "":[string]$i.Length
        $name = [string]$i.Name

        # num を表示する
        Write-Host $num.PadRight(7,' ') -NoNewLine;
        
        Write-Host $mode.PadRight(8,' ') -NoNewLine; 
        Write-Host $last.PadRight(20,' ') -NoNewLine; 
        Write-Host $len.PadLeft(10,' ') -NoNewLine;
        Write-Host "  " -NoNewLine; 
        Write-Host $name

        # 変数 $a に +1 する
        $a = $a + 1
        
    } 
    Write-Host ""

    # 標準入力を使用して開きたいファイルの番号を入力させる
    $ib = (Read-Host ファイルまたはディレクトリの番号を入力して下さい )

    # 変数 $b を使用して 入力されたものが int型 かどうか判定する処理
    $b = 0
    if([int]::TryParse($ib,[ref]$b)){

        # $ib が配列の length と一致しているかを判定する処理
        if(($b -gt 0) -and (($b -lt $child_items.Count + 1) -or ($b -lt 2))){

            # コンソールの表示と配列番号を一致させて各要素に代入
            $x = $b - 1
            $mode = [string]$child_items[$x].Mode
            $name = [string]$child_items[$x].Name
            $dir = [string]$current_dir + '\' + $name 

            # ディレクトリが指定された場合の処理 cd または Set-Location
            if($mode.Substring(0,1) -eq "d"){
                Set-Location $dir
                Write-Host ""

            # 拡張子ごとに指定したエディタで開く場合の処理（例： VScode で開く）
            }elseif($name.Substring(($name.Length -3),3) -eq ".py" -or 
                        $name.Substring(($name.Length -3),3) -eq ".hx"){
                code $name

            # その他のファイルを開く処理
            }else{
                Invoke-Item $name
                Write-Host ""
            }

        # 入力した数字が配列のレンジから外れている場合のメッセージ
        }else{
            Write-Host エラー：選択された番号にはアイテムがありません
            Write-Host ""
        }

    # 入力したものが int型 ではない場合のメッセージ
    }else{
        Write-Host エラー：番号が入力されませんでした
        Write-Host "" 
    }
    
    $current_dir = $child_items = $mode = $last = $len = $name = $a = $ib = $b = $null
    [GC]::Collect()
}

```

Microsoft.PowerShell_profile.ps1 ファイルを保存して閉じます。
ファンクションを使用出来る様にする為、PowerShell でプロファイルを更新します。

```ruby:PowerShell
> . $profile
```

実行
```ruby:PowerShell
> lsl

ディレクトリ：D:\Shits\HFprojects\ActionRoom

Num    Mode    LastWriteTime        Length     Name
-----  ------  -------------------  ---------  ------------------------------
1      d----   03/20/2025 13:07:16             .vscode
2      d----   03/20/2025 13:07:16             assets
3      d----   03/20/2025 13:07:16             dump
4      d----   03/20/2025 13:07:17             export
5      d----   03/20/2025 13:07:22             source
6      -a---   04/14/2024 21:02:09        240  hxformat.json
7      -a---   01/06/2025 22:48:56       3386  Project.xml

ファイルまたはディレクトリの番号を入力して下さい:2

```

2を選択して、もう一度 lsl を実行すると、

```ruby:PowerShell
> lsl

ディレクトリ：D:\Shits\HFprojects\ActionRoom\assets

Num    Mode    LastWriteTime        Length     Name
-----  ------  -------------------  ---------  ------------------------------
1      d----   04/05/2025 15:08:13             data
2      d----   03/23/2025 14:22:50             images
3      d----   03/20/2025 13:07:16             music
4      d----   03/20/2025 13:07:16             sounds

ファイルまたはディレクトリの番号を入力して下さい:

```

無事カレントディレクトリが移動しました。（ファイルの番号を選択した場合は開きます）

簡単なファンクションですが筆者はこれで少し作業ストレスが軽減しました。満足です。
PowerShell 勉強中の方と共有したくて記事にしたので、ここまで読んで下さったのならさらに言う事無しです。有難うございました。