WindowsのDOSコマンドは、長ったらしくてイライラする!!
Unixのcd -
って便利だよね! なんでWindowsではできないんだろう orz
そんな貴方に、DOSのAutoRunスクリプトを利用したハックを紹介します。
動作確認環境
- 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
の名前で保存します。
@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
と同じディレクトリに保存します。
そしてダブルクリック!!
@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