手間を削減!CLIでディレクトリ作成・直後に移動するを簡単にする方法(トホホ編?)

いままでもずっと手間だなと感じてはいたのですが、「ディレクトリを作成してすぐにそのディレクトリに移動するということ」。これまでは非IT系のジャンルにいたので、CLIなどの作業はあまりありませんでしたが、最近はその職から離れ、開発的なところにいるので、CLIを頻繁に使用するようになりました。そうなると、ディレクトリの作成・移動がとても頻繁にあるし、かなり面倒に感じて来ました。そこで、もう少し簡単に出来ないかと感じ、調査・改善をすることにしました。

大した内容ではないのでメモです。

bashでの改善

具体的には以下の2つのコマンドを短縮したいということになります。

初期状態

$ mkdir hoge
$ cd hoge

ワンライナーに変更するとなると以下のようになります。 &&は前段(左側のコマンド)が成功したら後段(右側のコマンド)を実行するというものになります。 1行にはなりましたが、タイプ数がほぼかわりません。

ワンライナー化 その1

$ mkdir hoge && cd hoge

さらにもう少し短縮するとなると以下のようになります。

ワンライナー化 その2

$ mkdir hoge && cd $_

$_は、直前のコマンドで最後に使った引数を参照するため、hogeに移動できます。これでディレクトリが長くなればかなりのタイプ数を減らすことができるようになりました。サブディレクトリの直接作成を考えるのであれば、mkdirに-pオプションをつけてもいいですね。そうすると途中作成していないディレクトリがあっても自動で生成してくれます。

例えば、mkdir -p foo/bar/bazのように使うと、foobarbazディレクトリがすべて存在しない場合に、一度に全てを作成します。また、既に指定したディレクトリが存在する場合もエラーを出さずにそのまま実行ができます。

ちなみに-pparentsの略になります。

ワンライナー化 その3

$ mkdir -p ./fuga/hoge && cd $_

これで結構楽になりました😊

bashの関数として定義してみる

先ほどのワンライナーの内容をbash関数として定義すればもっと短く実装も可能です。

.bashrcに以下の関数を追記します。

mkdirとcdの組み合わせをする関数mkcd

mkcd() {
    mkdir -p "$1" && cd "$1"
}

.bashrcファイルを編集して追加してもいいのですが、以下のコマンドを実行すれば、即追加できます。以降は.bashrcが読み込まれれば使用することができます。

$ echo 'mkcd() { mkdir -p "$1" && cd "$1"; }' >> ~/.bashrc
$ source ~/.bashrc

以降は以下のように実行できます。

$ mkcd hoge

これでかなり短くなりました🤩

WindowsPowerShellでの改善

すべての環境がbashであれば特に問題ないのですが、Windowsの場合はPowerShellでも同様のことが発生します。このときに関しても改善ができないかを同様に考えました。

対象とするのは以下です。bashと見た目はかわりません。

PS> mkdir hoge
PS> cd hoge

純粋にPowerShellを使用すると以下のようになります🤨

PS> New-Item -ItemType Directory -Path "hoge" -Force; Set-Location "hoge"

長い、長すぎる

PowerShellはコマンドにエイリアスがあり、New-Item -ItemType DirectoryエイリアスmkdirSet-Locationエイリアスcdとなります。

そのため、以下でよいのですが…以下で実行すると、New-Item -ItemType Directoryで適用している-Forceの機能はなくなります。また、bash&&となっていた部分は;に置き換えられていますが、これはbash&&と違い、成功失敗にかかわらず次のコマンドを実行してしまいます。これはかなり難問。

PS> mkdir "hoge"; cd "hoge"

もし、同じ意味実行し、キータイプを短縮するのであれば、PowerShellのコマンドやオプションの短縮表記を使用して以下のように実行することになります。結構マシですが、何言ってるかわからないコマンドになったような…

【短縮表記】 - New-Item → ni - ItemType → -i - Path → -p - Set-Location → sl

PowerShellでのワンライナー

PS> ni -i Directory -p "hoge" -Force; sl "hoge"

これを記憶する自信はない😢

PowerShellのプロファイルに関数として定義する

では、bash関数のように関数化できないかを考えます。PowerShellでは.bashrcのような設定ファイルとして$PROFILEが存在します。(パスはそれぞれですが、$PROFILEとすることで参照としては一意になります)

$PROFILEの実際のファイルはこちらになります。

PS> echo $PROFILE
C:\Users\【ユーザ名】\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1

ファイルがないこともあるので以下のようにファイルを作成します。存在していなければ$PROFILEを作成するというものです。

$PROFILEのファイル作成

PS> if (!(Test-Path -Path $PROFILE)) {
    New-Item -ItemType File -Path $PROFILE -Force
}

$PROFILEへ関数の追加と設定の反映

# $PROFILEへ追加
$ Add-Content -Path $PROFILE -Value @'
function mkcd { param($path) New-Item -ItemType Directory -Path $path -Force; Set-Location $path }
'@

# なんらかのスクリプト実行ポリシーの変更が必要(今回は*RemoteSigned*としている)
# 現在のセッションのみでスクリプト実行ポリシーの変更をしています。
PS> Set-ExecutionPolicy RemoteSigned -Scope Process -Force 

# 設定の反映
PS> . $PROFILE
# 現在のセッションでも必要があればスクリプト実行ポリシーは戻してください。

これで以下のように実行できます。

PS> mkcd hoge

この手法ではPowerShellスクリプト実行ポリシーを操作しているので、あまりいい手段ではない感じですが、仕方ないのでしょうか?ポリシーはデフォルトから変えたくない場合はどうするのか、まだ分かっていません。

これほどの手間なら、もはや以下でもいいのかも🥲

PS> mkdir hoge; cd hoge

おわりに

今回は日々のCLI操作で煩わしいと感じるディレクトリの作成直後のそのディレクトリへの移動について、より簡単に実行する方法を模索しました。bashではワンライナー化や関数定義によって、少しでも手間が減りコーディングや作業効率が向上しましたが。PowerShellでは実行ポリシーの部分が解決していないので今ひとつとなってしまいましたが、ポリシーさえ解決すれば…みなさんってスクリプト実行ポリシーって変更してるんですか?🤔

ということで、何かあったらまた追記したいと思います。

/* -----codeの行番号----- */