LoginSignup
7

More than 5 years have passed since last update.

posted at

updated at

Windowsで「cd -」や「ls」

WindowsのDOSコマンドは、長ったらしくてイライラする!!
Unixのcd -って便利だよね! なんでWindowsではできないんだろう orz

そんな貴方に、DOSのAutoRunスクリプトを利用したハックを紹介します。

example.jpg

動作確認環境

  • Windows 7
  • Windows Vista

導入方法

ごたくはいいからやり方だけ教えて! な貴方は、次の部分だけ読めば大丈夫です。

DOSのAutoRunとは

指定したDOSスクリプトを、cmdの起動時に実行させることができます。

  • Win+R ⇒ cmd で起動したDOS窓に適用されます
  • Explorerのアドレスバーにcmdと入力して起動したDOS窓に適用されます
  • atコマンドや*.batをダブルクリックで起動したDOSスクリプトにも適用されます

(後述する) 指定したユーザが起動したすべてのcmdに適用されます!!

注意事項

  • 初期ディレクトリ変更をした場合、多くのDOSスクリプトが正常に動作しなくなります
    ⇒ たいていのDOSスクリプトは「作業ディレクトリ=DOSスクリプトのディレクトリ」を前提としているため
    ⇒ DOSスクリプトの先頭でcd /d %~dp0をすれば回避できるが、このような配慮あるスクリプトはあまり見かけないため
  • やりすぎに注意!! 

DOSのAutoRunスクリプト

このDOSスクリプトを、dos_profile.batの名前で保存します。

dos_profile.bat
@echo off

rem プロンプト
prompt $g 

rem エイリアス
doskey pwd=cd
doskey cat=type $*
doskey ls=dir /w $*
doskey ll=dir $*
doskey la=dir /a:h
doskey mv=move $*
doskey rm=del $*
doskey ln=mklink $2 $1
doskey clear=cls

rem エイリアス:エディタ
set VI_EDITOR=C:\Program Files\EmEditor\EmEditor.exe
doskey   vi="%VI_EDITOR%"    $*
doskey view="%VI_EDITOR%" /r $*
set VI_EDITOR=

rem エイリアス:cd
set PREV_PWD_FILE=%TEMP%\pwd.prev
set PREV_PWD_TEMP=%TEMP%\pwd.temp
doskey cd=if ""=="$1" (^
    @cd ^
) else if "-"=="$1" (^
    @for /f "usebackq tokens=*" %%i in ^(`cd`^) do @echo %%i^>"%PREV_PWD_TEMP%" ^& ^
    @for /f "usebackq tokens=*" %%i in ^("%PREV_PWD_FILE%"^) do @cd "%%i" ^&^& ^
    @type "%PREV_PWD_FILE%" ^& ^
    @type "%PREV_PWD_TEMP%" ^> "%PREV_PWD_FILE%" ^
) else (^
    @for /f "usebackq tokens=*" %%i in ^(`cd`^) do @echo %%i^>"%PREV_PWD_TEMP%" ^& @cd $* ^&^& @type "%PREV_PWD_TEMP%" ^> "%PREV_PWD_FILE%" ^
)
set PREV_PWD_FILE=
set PREV_PWD_TEMP=

プロンプトの変更

規定値ではカレント・ディレクトリが表示されます。
長すぎるので>に変更。 文末に半角スペースを置くと可読性が向上します。

DOSKEYによるエイリアスの割り当て

DOSコマンドに、Unixライクなエイリアスを割り当てます。

補足:ln

Windowsのmklinkは、何故かUnixのlnと引数が逆転しています。

  • Unix ln ... ln FILE LINK
  • Windows mklink ... mklink LINK FILE

後発であるmklinkがなぜ引数を逆転させる必要があるのか?
Microsoftの 馬鹿な 残念な仕様に振り回されないよう、エイリアスを割り当てます。

mklinkの実行には、DOS窓を管理者権限で実行する必要があります。
※詳細は異なるが、ざっくりなら管理者権限で実行すればOK

ディレクトリのシンボリックリンクを作る場合は、/dスイッチを指定する必要があります。
引数を逆転させている関係で、空白を含むパスにリンクを貼る場合は失敗するかもしれません。 あしからず。

補足:エディタ

お好みのエディタを、VI_EDITOR環境変数に指定してください。
⇒ atomは初期起動が遅すぎるため、僕はカジュアルなテキストエディタとしては使ってません

補足:cd

やってることは単純で、次のようになります。

  • 引数なし
    • 作業ディレクトリを表示
  • 引数="-"
    • 作業ディレクトリをpwd.tempに退避
    • cd pwd.prevの退避ディレクトリ
    • cdが成功したら、移動先を標準出力してからpwd.prevに元の作業ディレクトリを退避
  • 上記以外
    • 作業ディレクトリをpwd.tempに退避
    • cd パラメータ
    • cdが成功したら、pwd.prevに元の作業ディレクトリを退避

これらをdoskeyの記述ルールに従って表現するのに、実はかなり苦戦しました。

利用した構文
  • ^ ... DOSのエスケープ文字です。 行末に記述してあるのは行継続。
  • @ ... コマンドのエコーバックを抑制してます
  • ^> ... リダイレクトです。 MSDNには$gと記載されていますが、英字だと直感的ではないのでエスケープ文字で代替。
  • ^& ^&^& ... コマンド結果演算です。 MSDNには$tと記載されていますが、英字だと直感的ではないのでエスケープ文字で代替。
制限事項

作業ディレクトリの退避ファイル名を固定にしているため、 同時に複数のcmdを実行している場合はcd -が正しく機能しません
他プロセスも含めて、最後にcdを実行した時の元ディレクトリへ移動します。

僕は「Windowsで複数ターミナルを起動&cd -も使い倒す」的なシチュエーションはめったになくこの仕様で困ることはないのです が、記事を公開するにあたっては不親切仕様であるので、いずれ次のように改修しようと思います

  • 退避ファイルをpid毎に分ける
  • ログオフスクリプトで退避ファイルを削除

powershellを利用してpidを取得してみたのですが、DOS窓を起動するたびにクッと引っかかるようになったため改修はやめました。

pushd/popdを使っても戻る操作を表現できますが、ネスト制限について書かれた文書が見つからなかったため不採用としました。
⇒ 基本操作であるcdの振る舞いを書き換えており、これによる想定外の事象を嫌ったため

DOSのAutoRunスクリプトを指定

次のいずれかのレジストリにAutoRunという名前でDOSスクリプトを指定します。
適用スコープに応じたレジストリを編集してください。

レジストリ・キー 適用スコープ 備考
HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor すべてのユーザ
HKEY_CURRENT_USER\Software\Microsoft\Command Processor 現在のユーザ おすすめ
名前 種類 設定値(例)
AutoRun REG_SZ C:\xxx\xxx.bat

お手軽な指定方法

このDOSスクリプトを、前述したdos_profile.batと同じディレクトリに保存します。
そしてダブルクリック!!

dos_profile_regist.bat
@echo off

reg add   "HKEY_CURRENT_USER\Software\Microsoft\Command Processor" /v AutoRun /d %~dp0dos_profile.bat
reg query "HKEY_CURRENT_USER\Software\Microsoft\Command Processor" /v AutoRun

pause

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
7