前回のつづき。
前回まで
ファイルを一発作成したい。秀丸ファイラで一発ファイル作成(PowerShellインライン版)でできたが、実行速度が遅すぎた。
そこで前回、Linuxコマンドで実装しようとした。しかし、出力先ディレクトリを指定することができなかった。
今回
出力先ディレクトリを指定することができなかった経緯。
対象環境
- Windows XP Pro SP3 32bit
- cmd.exe
- ConEmu
- 秀丸ファイラ 1.10
やりたかったこと
MinGW/msysでは以下のコマンドで実行できる。
dir='C:\\あ い\\'; fname=`date '+%Y%m%d%H%M%S%3N.py'`; touch "$dir$fname";
cmd.exeでは以下のコマンドで実行できる。
bash -c "dir='C:\\あ い\\'; fname=`date '+%Y%m%d%H%M%S%3N.py'`; touch \"$dir$fname\";"
上記コマンドのディレクトリ部分C:\\あ い\\
を秀丸ファイラのカレントディレクトリ%V
にしたい。
C:\MinGW\msys\1.0\bin\bash.exe -c "dir='%V'; fname=`date '+%Y%m%d%H%M%S%3N.py'`; touch \"$dir$fname\";"
しかし、これは動作しない。WindowsとLinuxのパス区切記号が違うことが原因である。
問題
パス区切記号
問題はパスの区切文字である。
秀丸ファイラの%V
でディレクトリ文字列を渡せる。しかし、そのパス区切記号が\
なのが問題になる。\
はLinuxシェル上ではエスケープ文字である。たとえばC:\a\b\
だと、C:ab
になってしまう。Linuxシェル上でのパス区切記号は\
である。シェルに渡す前に\
を/
に置換する必要がある。または、\\
のようにする必要がある。
インラインにできない
Windowsのコマンドで\
を/
に置換する方法はある。set dir=%V
で変数にディレクトリ名を入れ、set dir=%dir:\=/%
とすることで置換できる。しかし、バッチファイルにしないと使えない。パイプ連結したコマンドでは使えない。結果、秀丸ファイラでインライン・コマンドとして登録することができない。
replace.bat
set dir=C:\a\b\ echo %dir:\=/% set dir=C:\a\b\ set dir=%dir:\=/% echo %dir% pause
置換するには一度変数に代入せねばならない。しかし、インラインにすると代入ができなくなった。その経緯は以下。
&
で繋げても変数の状態が継承されない
"Batch 1行に複数文"で検索するとこちらがヒット。感謝。Batchでは1行に複数文を書くとき、&
を使うらしい。Shellでは;
だった。
> echo a & echo b a b
これを使ってパス区切記号\
を/
に置換してからbashに渡すつもりのコマンドを以下に書いた。
set dir=%V & set dir=%dir:\=/% & bash -c "dir=%dir%; fname=`date '+%Y%m%d%H%M%S%3N.py'`; touch \"$dir$fname\";"
しかしset dir=...
での代入が反映されなかった。順に検証する。
まずはcmd.exeにて以下のコマンドを叩いてみた。ディレクトリ名にC:\dir
を仮に設定しておく。
set dir=C:\dir & set dir=%dir:\=/% & bash -c "dir=%dir%; fname=`date '+%Y%m%d%H%M%S%3N.py'`; touch \"$dir$fname\";"
しかし、Windowsのset dir=C:\dir
が反映されていない。
set dir=C:\dir & echo %dir%
以下のようにすると代入される。
set dir=C:\dir echo %dir%
しかし上記は改行コードが含まれるためバッチファイルに書くしかない。インラインにできない。
どうやら&
で繋ぐと変数の状態は継承されないらしい。Linux(sh,bash)の;
で繋ぐ方法なら変数の状態を継承できたのに…。でも、Linux(sh,bash)に\
のパス区切記号を使った文字列を渡してもエスケープされてしまうから肩代わりできない…。
かくしてインラインを断念し、スクリプトファイルにすることと相成った。
ほかの方法
Windows
諸悪の根源はパス区切記号である。やはりWindows、お前か。
dateコマンド
べつにWindowsコマンドだけで解決できれば、Linuxコマンドなど使わずにすんだ。パス区切記号が何であれ、問題にはならなかった。しかし、WindowsのdateコマンドはLinuxのdateコマンドのようにフォーマットできない仕様…。
%time%
, %date%
じつはWindowsには%time%
, %date%
という日時を取得できる特殊な変数がある。しかし、バージョンによって取得できる書式が異なっているなど汎用性にかける。また、一部ゼロ埋めされていないなどの問題もある。その加工には置換が必要。先述のとおり、置換するにはバッチファイル化が必要でありインラインにできない。
学習が無駄になりそう
動作するなら何でもいいが、せっかくなら学習や成果物を流用できる可能性が高いほうがいい。そう考えるとWindowsよりLinuxになる。元々使えない上に、すでにオワコンOSのコマンドにそこまで執心するより、未来のあるLinuxコマンドで実装したほうが幸せになれると思った。
PowerShellは重い
WindowsにはPowerShellがある。これで解決したのが秀丸ファイラで一発ファイル作成(PowerShellインライン版)である。実行速度が遅いので別解を求めている最中。
Python
ところで、未だにbatch, shellで悩み続けている。糞スクリプトであるBatchから脱却したくてPythonを使ってみたのに今回は使えていない。Pythonではコマンド環境でインラインはできない、と思うから。
ググるとこちらがヒット。感謝。しかし、結局Pythonファイルを作成するのでインラインにはできなそう。ぐぬぬ。